HiveMQ MQTT Client Java: Is there a way to check if a topic matches a subscription?

1.4k views Asked by At

Is there a built in way to check with hivemq-mqtt-client if a specific topic matches another topic in advance?

For instance, a message published with topic:

publishedTopic= "sensors/sensor1";

A client that subscribes:

subscribedTopic = "sensors/#";

Is there something like

publishedTopic.matches(subscribedTopic)

?

The exact situation:

I run a broker in my house, several devices publish values with different topics. Some like sensor/humi[45], some like sensor/data[JSON Payload]. For my personal use I run an application using Java HiveQM MQTT clients. One client is subscribed to relevant topics using mosquitto on raspberryPi. The other client is publishing selected data to a public accessible broker. Receiving a new message will not only process all data in the way I process it but also trigger a publishing the received message to the public broker.

Yes, I can

if(topic.equals("sensor/xxx")) {
//publish to public broker here
}

But doing some like subscribing to "sensor/#", from my internal broker, and "forwarding" something like "sensor/+", and letting a library doing the job of determining if a certain message that is received with "sensors/#", will be republished to the public broker, limited to "sensors/+" is what I am looking for.

Is the logic inside HiveMQ mqtt-client library, which obviously filters in that exact way, when I subscribe to "sensors/#", accessible for the library user?

3

There are 3 answers

2
Odysseus On BEST ANSWER

One way to achieve what you want is to use a particular callback for the topics you want to forward.

Using HiveMQ library you can define a callback to consume the received message per subscribe or globally matching a given filter.

In your case you could use a per subscribe consumer for the topics which should be handled in a special way:

client.subscribeWith()
        .topicFilter("sensors/sensor1")
        .qos(<qos>)
        .callback(<callback for topics to be forwarded>)
        .send();

Followed by a global filter matching all topics which are not yet consumed:

client.publishes(MqttGlobalPublishFilter.REMAINING, <callback for other topics>))

(and the subscription to sensors/# of course)

This way only sensors/sensor1 will be consumed in your first callback and sensors/sensor2, sensors/sensor3 (and so on) are consumed by the other callback

1
hardillb On

Part of the point of MQTT is to totally decouple the information producers from the consumers. This means that a client publishing a messages to a topic knows absolutely nothing about any clients that may be subscribed to the topic that the message is published to.

There may be any where from 0 to infinite subscribers and they may be subscribed to just the exactly matching topic or a wildcard that will match.

In the situation you describe in the comments, where you have a bridge between 2 brokers, you will need to explicitly list the topics you want to bridge, normally you can not change that list dynamically based on what a given client connected to the one of the brokers is subscribed to.

You might be able to write a plugin for HiveMQ that would do this, but it would have to run on the same broker that the client subscribes to which if I've understood correctly is the one you don't have control over.

2
Charlie Reitzel On
import com.hivemq.client.mqtt.datatypes.MqttTopic;
import com.hivemq.client.mqtt.datatypes.MqttTopicFilter;
...

class Example {
    static boolean matches( String topicFilter, String topicReceived ) {
        MqttTopicFilter filter = MqttTopicFilter.of(topicFilter);
        MqttTopic topic = MqttTopic.of(topicReceived);
        return filter.matches(topic);
    }
}