MQTT-SN how to "UNREGISTER" a given topic when using wildcard? - mqtt

I am using the paho library (in C language) for MQTT-SN implementation on a BC660K dev-kit.
So far, I am able to do any common stuff like publish, subscribe, etc. as anyone would expect.
However, I now need to use a wildcard, to subscribe like this:
a/b/+/c
The subscription is working fine.
So, if someone writes on, let's say, this topic:
a/b/12345/c
I am able to receive the message. To make it short, the funcionality is working fine.
However, I noticed that the MQTT-SN does the following (at low level):
ClientA sends SUBSCRIBE to topic a/b/+/c
MQTT-SN-Gateway answers with SUBACK message, and topic-id == 0 (following the specification)
On clientB, I publish on topic a/b/123/c which matches the wildcard in ClientA.
MQTT-SN-Gateway then sends a REGISTER{topic-id=789,a/b/123/c} message to ClientA.
ClientA then replies with REGACK to MQTT-SN-Gateway
MQTT-SN-Gateway then sends the data via PUBLISH with the topic-id=789 to ClientA
ClientB sends again something on a/b/123/c
MQTT-SN-Gateway sends the data via PUBLISH with the topic-id=789 to clientA
So, as you can see, at step 4, the Gateway assigns a topic-id to that topic ClientB published. So, on any new incoming messages, Gateway uses the topic-id rather than the string to represent the topic.
However, what I need for my particular case is to UNREGISTER from that topic as soon as I receive something. And, if I receive something again on that same topic, I would like to do the steps 4,5, and 6.
For this, I tried the following:
ClientA after receiving data, sends an UNSUBSCRIBE{topic-id=789}
MQTT-SN-Gateway answers with the UNSUBACK
ClientB sends some data on a/b/123/c again
MQTT-SN-Gateway then sends the payload via PUBLISH with the topic-id=789 to clientA
Thus, the Gateway does not re-REGISTER again the topic with the ClientA (that is what I would expect).

By checking the documentation MQTT-SN 1.2 Spec at section 7.3 Mapping of Topic Ids to Topic Names the mapping is per client during a session.
So, my assumption that the MQTT-SN-Gateway would re-assign a topic-id for the same topic is wrong.
The correct behavior is that the client is the same, and the assignment of the topic-id was already done, the MQTT-SN-Gateway will keep the same topic-id as long as the client is connected.

Related

MQTT paho client publish message and delete immediately the receiver consumes it

I have been trying to work with paho mqtt client to publish and receive messages with mosquitto as the broker and works fine. My use case although involves the sender publishing a message to the broker and disconnects, at this point, the receiver whether connected or disconnected should consume this message and delete it immediately. I have played with all the properties e.g QOS, retained messages, clean sessions, etc but none is yielding the result I want. Please help.
Assuming a Publish and Subscription at QOS2 the message will only ever be delivered to the subscriber once, there is nothing to delete from anywhere.
If you are trying to ensure that the message is only ever consumed by one specific client then I think you have a misunderstanding about what MQTT is.
MQTT is a PUB/SUB protocol, and as such is designed to totally decouple the subscriber from the publisher. The publisher doesn't know how many subscribers there are, just that it has published a message to a given topic.
0 to N (where N can be any number) of clients can subscribe to the topic. Using QOS, persistent subscriptions and the clean session flag, a client can indicate to the broker that it would like to receive any messages published since was last connected, but this will not influence any other clients that may have also subscribed to that topic.
Starting at MQTT protocol v5 (most brokers and clients currently still only support v3 as of Sept 2018) includes something called Shared Subscriptions* that can be used to round-robin deliver messages on a give topic to a group of clients so only 1 of the set will receive this message, but this does not prevent clients not part of the group from also receiving the message.
The last message with the retained flag set published to a topic will be delivered to all clients at the point they subscribe to the topic. This message can be cleared by publishing a new message with a null payload and the retained flag set. A client could publish a message like this as soon as it receives the retained message but there would still be a timing window where other clients may subscribe and receive the retained message.
*some v3 brokers have implemented propriety versions of this.

How to publish a message to a specific client in Mosquitto 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!
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.
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...

How to check when a broker has delivered a message to a client(Subscriber)

I am implementing the Paho MQTT Java client for my android project. It is basically an instant messaging system. The publish and subscribe implementation is working very well for me, but I am left with an issue. Subscribed clients are able to receive messages when they are published, however the ability for the system to check when a messaged is received/delivered by the client(subscriber) or not is a bit difficult to implement, this I think its because MQTT does not support that.
Does anybody has an idea as to how to implement this logic in a different way?
The MQTT protocol has no built in End to End delivery notification. There is no way of knowing how many subscribers there is to a topic, it could any where between 0 and many.
If you need End to End delivery notification then you need to build it into your application, by adding a unique id to the payload of each message and then publishing another message (probably on a separate topic) with that id from the client subscribed to the original topic. Messages should also be published and subscribed at QOS 2 to ensure they are only delivered once.
As per the documentation on the MQTT you can set the MqttCallback which has the method deliveryComplete(IMqttDeliveryToken token) now as per the documentation it states that this callback method will be called
when delivery for a message has been completed, and all acknowledgments have been received.
To ensure the delivery set the QoS (Quality of Service) to 2.
If you still have doubts about this approach you can use another approach where you can expect the acknowledgement message from the client on the delivery of the message, however this is just another overhead to the mqtt and it's up to the requirement of yours to use this or not.
You can explore more on their github it also has the sample code to know more about the workings of Mqtt.
I hope this helps

MQTT know if a client is subscribed (cont)

Today I posted this topic
MQTT know if a client is subscribed
I would like to try something, but I would like to know if is feasible, may be I'm complicating the things, so if you have another suggestion please feel free
let's suppose that we have the topic temperature/subscription
First
Client A subscribes to subscription (or in other words temperature/subscription)
if he doesn't receive a payload (a retain message)
then
Client A publishes to subscription with a payload of 1 or "online" as a retain message
and subscribes to the temperature topic
Now, Client B
again, subscribes to subscription if he receives a payload = someone is already subscribed (Client A)
So, he can't subscribe to temperature topic
I still need to add the LWT message, but first I want to start with something simple.
Is it feasible to do this? so I this way I can see if someone is subscribed or not to a topic
As we discussed last time, that will work, but it has a huge gaping timing window between checking for a message on temperature/subscription and publishing a message to it to claim the subscription.
Also you need to use the client id of as the marker because retained messages will survive a broker restart, which will disconnect all the client, so client A won't know it still holds the "lock" after a broker restart.
The LWT is only there for is client A crashes and then it will wait for the TTL for the connection to expire before sending the message, you need to explicitly clear that topic if client A disconnects cleanly.
In summary this is a really bad idea, trying to retro fit a concept that MQTT is not suited to.

Receive offline messages mqtt

I'm using mosquitto as broker and paho(python) as client. I'm trying to make subscriber to receive offline messages.
For that I made following changes:
Fixed client ID
qos level 2
but, still the subscriber is not able to receive messages.
any help?
Thanks,
Rahul
In order to have your client as a durable client and receive messages that were sent to topics when it was offline, you need to meet the following criteria:
Fixed client ID (as you've done)
Always connect with clean_session=False
Subscriptions must be made with QoS>0
Messages published must have QoS>0
The mistake that I make most frequently is to forget either one of points 3 and 4, so I'm publishing with QoS=0 or subscribing with QoS=0, either of which would cause messages not to be stored.
You could also look at the queue_qos0_messages option to tell the broker to store QoS=0 messages as well. Note that this is an implementation detail that may be specific to mosquitto.
Check if you have set the retain flag to true when publishing message to topic, with retain=true, new connected client which subscribes the topic will receive the retained message.

Resources