
Wildcard | Description | Example |
+ | A single-level wildcard, representing matching exactly one arbitrary topic level. | Subscribe to sensor/+/temperatureMatch sensor/bedroom/temperatureMatch sensor/living_room/temperatureDoes not match sensor/bedroom/upstairs/temperature (because + can only match one level).sensor/temperature is not matched (because there is a missing level between sensor and temperature). |
# | A multi-level wildcard, representing matching zero or more arbitrary topic levels, must be the last character of the topic filter. | Subscribe to sensor/bedroom/#Match sensor/bedroom/temperatureMatch sensor/bedroom/humidityMatch sensor/bedroom/light/intensityMatch sensor/bedroom (# can match zero levels).sensor/living_room/temperature is not matched (because bedroom is fixed). |
QoS Level | Workflow | Advantage | Disadvantages | Scenarios |
QoS = 0 (At most once) | The sender sends the message without requiring acknowledgment from the receiver. | The transmission speed is the fastest and the overhead is the lowest. | Messages may be lost in cases such as network failures or when the receiver is offline. | Non-critical data that can tolerate occasional loss, such as periodic sensor data (temperature, humidity), where a lost data point will soon be replaced by the next one. |
QoS = 1 (At least once) | 1. The sender sends the message and retains a copy. 2. Upon receiving the message, the recipient must reply with a PUBACK (Publish Acknowledgment) packet. 3. The sender will only discard the message copy after the PUBACK is received. 4. If the sender does not receive PUBACK within a reasonable time, it will resend the message. | Ensures that messages are not lost. | This may result in message duplication. | Guaranteed message delivery is required, and occasional duplication is acceptable. For example, control commands ( "turning on/off lights" ) may still function correctly even if they are executed more than once. |
QoS = 2 (Exactly once) | 1. PUBLISH: The sender sends the message and retains a copy. 2. PUBREC: Upon receipt, the recipient replies with a "received" acknowledgment. If the sender does not receive PUBREC, it will resend the PUBLISH. 3. PUBREL: Upon receiving PUBREC, the sender transmits a "Publish Release" message and can discard the message copy. It now only needs to await final confirmation. 4. PUBCOMP: Upon receiving PUBREL, the recipient replies with a "Publish Complete" acknowledgment. Only then is the message delivered to the application. The sender concludes the process upon receiving PUBCOMP. If either party fails to receive a response, they will resend the previous packet. | Ensures that messages are not lost while guaranteeing non-duplication. | The speed is the slowest and the overhead is the highest. | For mission-critical operations that demand extremely high reliability and accuracy, such as billing systems, financial transactions, and critical state synchronization, any duplication or loss would lead to serious consequences. |
retained parameter to true. The Broker will then store the latest retained message for this Topic.sensor/temperature will immediately receive the latest temperature without waiting for the next hour.package com.tencent.tdmq.mqtt.example.paho.v5;import java.nio.ByteBuffer;import java.nio.charset.StandardCharsets;import java.util.List;import java.util.concurrent.TimeUnit;import org.eclipse.paho.mqttv5.client.IMqttToken;import org.eclipse.paho.mqttv5.client.MqttCallback;import org.eclipse.paho.mqttv5.client.MqttClient;import org.eclipse.paho.mqttv5.client.MqttConnectionOptions;import org.eclipse.paho.mqttv5.client.MqttDisconnectResponse;import org.eclipse.paho.mqttv5.client.persist.MemoryPersistence;import org.eclipse.paho.mqttv5.common.MqttException;import org.eclipse.paho.mqttv5.common.MqttMessage;import org.eclipse.paho.mqttv5.common.packet.MqttProperties;import org.eclipse.paho.mqttv5.common.packet.UserProperty;public class SubscriberQuickStart {public static void main(String[] args) throws MqttException, InterruptedException {// Get the access point from the MQTT console:// For users who implement VPC network integration via Private Link, use private network access point;// For users accessing over the public network, ensure the public network security policy permits access, and the machine running the program has public network connectivity;String serverUri = "tcp://mqtt-xxx.mqtt.tencenttdmq.com:1883";// A valid Client Identifier contains digits 0-9, lowercase English letters a-z, and uppercase English letters A-Z, with a total length of 1-23 characters// See https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901059String clientId = "SubscriberQuickStart";// On the console --> Create account on the Authentication Tab, copy username and passwordString username = "user0";String password = "secret0";// MQTT topic filtersString[] topicFilters = new String[]{"home/test", "home/#", "home/+"};int[] qos = new int[]{1, 1, 1};MqttClient client = new MqttClient(serverUri, clientId, new MemoryPersistence());client.setTimeToWait(3000);MqttConnectionOptions options = new MqttConnectionOptions();options.setUserName(username);options.setPassword(password.getBytes(StandardCharsets.UTF_8));options.setCleanStart(true);options.setAutomaticReconnect(true);client.setCallback(new MqttCallback() {@Overridepublic void disconnected(MqttDisconnectResponse response) {System.out.println("Disconnected: " + response.getReasonString());}@Overridepublic void mqttErrorOccurred(MqttException e) {e.printStackTrace();}@Overridepublic void messageArrived(String topic, MqttMessage message) {byte[] payload = message.getPayload();String content;if (4 == payload.length) {ByteBuffer buf = ByteBuffer.wrap(payload);content = String.valueOf(buf.getInt());} else {content = new String(payload, StandardCharsets.UTF_8);}System.out.printf("Message arrived, topic=%s, QoS=%d content=[%s]%n",topic, message.getQos(), content);List<UserProperty> userProperties = message.getProperties().getUserProperties();printUserProperties(userProperties);}@Overridepublic void deliveryComplete(IMqttToken token) {System.out.println("Delivery complete for packet-id: " + token.getMessageId());}@Overridepublic void connectComplete(boolean reconnect, String serverURI) {System.out.println(reconnect ? "Reconnected" : "Connected" + " to " + serverURI);try {// SubscribeIMqttToken token = client.subscribe(topicFilters, qos);int[] reasonCodes = token.getReasonCodes();for (int i = 0; i < reasonCodes.length; i++) {System.out.printf("Subscribed to topic %s with QoS=%d, Granted-QoS: %d%n",topicFilters[i], qos[i], reasonCodes[i]);}if (token.isComplete()) {List<UserProperty> userProperties = token.getResponseProperties().getUserProperties();printUserProperties(userProperties);}} catch (MqttException e) {e.printStackTrace();}}@Overridepublic void authPacketArrived(int i, MqttProperties properties) {System.out.println("Received auth packet with id: " + i);}});client.connect(options);TimeUnit.MINUTES.sleep(5);client.disconnect();client.close();}static void printUserProperties(List<UserProperty> userProperties) {if (null != userProperties) {for (UserProperty userProperty : userProperties) {System.out.printf("User property: %s = %s%n", userProperty.getKey(), userProperty.getValue());}}}}
Feedback