diff --git a/src/UserGuide/Master/Table/API/Programming-MQTT.md b/src/UserGuide/Master/Table/API/Programming-MQTT.md
index 91dec2b81..0ea8d2e15 100644
--- a/src/UserGuide/Master/Table/API/Programming-MQTT.md
+++ b/src/UserGuide/Master/Table/API/Programming-MQTT.md
@@ -22,20 +22,27 @@
## 1. Overview
-[MQTT](Message Queuing Telemetry Transport)(http://mqtt.org/) is a lightweight messaging protocol designed for IoT and low-bandwidth environments. It operates on a Publish/Subscribe (Pub/Sub) model, enabling efficient and reliable bidirectional communication between devices. Its core objectives are low power consumption, minimal bandwidth usage, and high real-time performance, making it ideal for unstable networks or resource-constrained scenarios (e.g., sensors, mobile devices).
+MQTT (Message Queuing Telemetry Transport) is a lightweight messaging protocol designed for IoT and low-bandwidth environments. It operates on a Publish/Subscribe (Pub/Sub) model, enabling efficient and reliable bidirectional communication between devices. Its core objectives are low power consumption, minimal bandwidth usage, and high real-time performance, making it ideal for unstable networks or resource-constrained scenarios (e.g., sensors, mobile devices).
IoTDB provides deep integration with the MQTT protocol, fully compliant with MQTT v3.1 (OASIS International Standard). The IoTDB server includes a built-in high-performance MQTT Broker module, eliminating the need for third-party middleware. Devices can directly write time-series data into the IoTDB storage engine via MQTT messages.
-
+
+## 2. Configuration
-## 2. Built-in MQTT Service
-The Built-in MQTT Service provide the ability of direct connection to IoTDB through MQTT. It listen the publish messages from MQTT clients
-and then write the data into storage immediately.
-The MQTT topic corresponds to IoTDB timeseries.The first segment of the MQTT topic (split by `/`) is used as the database name.The table name is derived from the `` in the line protocol.
-The messages payload can be format to events by `PayloadFormatter` which loaded by java SPI, and the implementation of `PayloadFormatter` for table is `LinePayloadFormatter`.
-The following is the line protocol syntax of MQTT message payload and an example:
+By default, the IoTDB MQTT service loads configurations from `${IOTDB_HOME}/${IOTDB_CONF}/iotdb-system.properties`.
+
+| **Property** | **Description** | **Default** |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------- | ------------------- |
+| `enable_mqtt_service` | Enable/ disable the MQTT service. | FALSE |
+| `mqtt_host` | Host address bound to the MQTT service. | 127.0.0.1 |
+| `mqtt_port` | Port bound to the MQTT service. | 1883 |
+| `mqtt_handler_pool_size` | Thread pool size for processing MQTT messages. | 1 |
+| **`mqtt_payload_formatter`** | **Formatting method for MQTT message payloads. ****Options: `json` (tree model), `line` (table model).** | **json** |
+| `mqtt_max_message_size` | Maximum allowed MQTT message size (bytes). | 1048576 |
+
+## 3. Write Protocol
* Line Protocol Syntax
@@ -49,23 +56,7 @@ The following is the line protocol syntax of MQTT message payload and an example
myMeasurement,tag1=value1,tag2=value2 attr1=value1,attr2=value2 fieldKey="fieldValue" 1556813561098000000
```
-
-
-## 3. MQTT Configurations
-
-By default, the IoTDB MQTT service loads configurations from `${IOTDB_HOME}/${IOTDB_CONF}/iotdb-system.properties`.
-
-Configurations are as follows:
-
-| **Property** | **Description** | **Default** |
-| ------------------------ | ---------------------------------------------------------------------------------------------------------------------- |-------------|
-| `enable_mqtt_service` | Enable/ disable the MQTT service. | false |
-| `mqtt_host` | Host address bound to the MQTT service. | 127.0.0.1 |
-| `mqtt_port` | Port bound to the MQTT service. | 1883 |
-| `mqtt_handler_pool_size` | Thread pool size for processing MQTT messages. | 1 |
-| **`mqtt_payload_formatter`** | **Formatting method for MQTT message payloads. ****Options: `json` (tree model), `line` (table model).** | **json** |
-| `mqtt_max_message_size` | Maximum allowed MQTT message size (bytes). | 1048576 |
-
+
## 4. Naming Conventions
@@ -102,24 +93,47 @@ The table name is derived from the `` in the line protocol.
## 5. Coding Examples
The following is an example which a mqtt client send messages to IoTDB server.
-```java
+ ```java
MQTT mqtt = new MQTT();
mqtt.setHost("127.0.0.1", 1883);
mqtt.setUserName("root");
mqtt.setPassword("root");
BlockingConnection connection = mqtt.blockingConnection();
+String DATABASE = "myMqttTest";
connection.connect();
-for (int i = 0; i < 10; i++) {
- String payload = String.format("test%d,tag1=t1,tag2=t2 attr1=a1,attr2=a2 field1=\"value1\",field2=1i,field3=2u,field4=3i32,field5=t,field6=false,field7=4,field8=5f 1", random.nextDouble());
-
- connection.publish("root.sg.d1.s1", payload.getBytes(), QoS.AT_LEAST_ONCE, false);
-}
+String payload =
+ "test1,tag1=t1,tag2=t2 attr3=a5,attr4=a4 field1=\"fieldValue1\",field2=1i,field3=1u 1";
+connection.publish(DATABASE + "/myTopic", payload.getBytes(), QoS.AT_LEAST_ONCE, false);
+Thread.sleep(10);
+
+payload = "test1,tag1=t1,tag2=t2 field4=2,field5=2i32,field6=2f 2";
+connection.publish(DATABASE, payload.getBytes(), QoS.AT_LEAST_ONCE, false);
+Thread.sleep(10);
+
+payload = "# It's a remark\n " + "test1,tag1=t1,tag2=t2 field4=2,field5=2i32,field6=2f 6";
+ connection.publish(DATABASE + "/myTopic", payload.getBytes(), QoS.AT_LEAST_ONCE, false);
+ Thread.sleep(10);
+
+//batch write example
+payload =
+ "test1,tag1=t1,tag2=t2 field7=t,field8=T,field9=true 3 \n "
+ + "test1,tag1=t1,tag2=t2 field7=f,field8=F,field9=FALSE 4";
+connection.publish(DATABASE + "/myTopic", payload.getBytes(), QoS.AT_LEAST_ONCE, false);
+Thread.sleep(10);
+
+//batch write example
+payload =
+ "test1,tag1=t1,tag2=t2 attr1=a1,attr2=a2 field1=\"fieldValue1\",field2=1i,field3=1u 4 \n "
+ + "test1,tag1=t1,tag2=t2 field4=2,field5=2i32,field6=2f 5";
+connection.publish(DATABASE + "/myTopic", payload.getBytes(), QoS.AT_LEAST_ONCE, false);
+Thread.sleep(10);
connection.disconnect();
+ ```
+
-```
## 6. Customize your MQTT Message Format
@@ -166,10 +180,10 @@ public class CustomizedLinePayloadFormatter implements PayloadFormatter {
for (int i = 0; i < 3; i++) {
long ts = i;
TableMessage message = new TableMessage();
-
+
// Parsing Database Name
message.setDatabase("db" + i);
-
+
//Parsing Table Names
message.setTable("t" + i);
@@ -200,7 +214,7 @@ public class CustomizedLinePayloadFormatter implements PayloadFormatter {
message.setFields(fields);
message.setDataTypes(dataTypes);
message.setValues(values);
-
+
//// Parsing timestamp
message.setTimestamp(ts);
ret.add(message);
@@ -232,6 +246,7 @@ Then, in your server:
More: the message format can be anything you want. For example, if it is a binary format,
just use `payload.forEachByte()` or `payload.array` to get bytes content.
+
## 7. Caution
To avoid compatibility issues caused by a default client_id, always explicitly supply a unique, non-empty client_id in every MQTT client.
diff --git a/src/UserGuide/Master/Tree/API/Programming-MQTT.md b/src/UserGuide/Master/Tree/API/Programming-MQTT.md
index df230ecd6..f99e0cdda 100644
--- a/src/UserGuide/Master/Tree/API/Programming-MQTT.md
+++ b/src/UserGuide/Master/Tree/API/Programming-MQTT.md
@@ -22,13 +22,13 @@
## 1. Overview
-[MQTT](Message Queuing Telemetry Transport)(http://mqtt.org/) is a lightweight messaging protocol designed for IoT and low-bandwidth environments. It operates on a Publish/Subscribe (Pub/Sub) model, enabling efficient and reliable bidirectional communication between devices. Its core objectives are low power consumption, minimal bandwidth usage, and high real-time performance, making it ideal for unstable networks or resource-constrained scenarios (e.g., sensors, mobile devices).
+MQTT (Message Queuing Telemetry Transport) is a lightweight messaging protocol designed for IoT and low-bandwidth environments. It operates on a Publish/Subscribe (Pub/Sub) model, enabling efficient and reliable bidirectional communication between devices. Its core objectives are low power consumption, minimal bandwidth usage, and high real-time performance, making it ideal for unstable networks or resource-constrained scenarios (e.g., sensors, mobile devices).
IoTDB provides deep integration with the MQTT protocol, fully compliant with MQTT v3.1 (OASIS International Standard). The IoTDB server includes a built-in high-performance MQTT Broker module, eliminating the need for third-party middleware. Devices can directly write time-series data into the IoTDB storage engine via MQTT messages.
-[Programming-MQTT.md](Programming-MQTT.md)
+
## 2. Built-in MQTT Service
The Built-in MQTT Service provide the ability of direct connection to IoTDB through MQTT. It listen the publish messages from MQTT clients
and then write the data into storage immediately.
@@ -62,15 +62,14 @@ The IoTDB MQTT service load configurations from `${IOTDB_HOME}/${IOTDB_CONF}/iot
Configurations are as follows:
-| **Property** | DESCRIPTION | DEFAULT |
-| ------------- |:-------------:|:------:|
-| `enable_mqtt_service` | whether to enable the mqtt service | false |
-| `mqtt_host` | the mqtt service binding host | 127.0.0.1 |
-| `mqtt_port` | the mqtt service binding port | 1883 |
-| `mqtt_handler_pool_size` | the handler pool size for handing the mqtt messages | 1 |
-| **`mqtt_payload_formatter`** | **Formatting method for MQTT message payloads. ****Options: `json` (tree model), `line` (table model).** | **json** |
-| `mqtt_max_message_size` | the max mqtt message size in byte| 1048576 |
-
+| **Property** | **Description** | **Default** |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------- | ------------------- |
+| `enable_mqtt_service` | Enable/ disable the MQTT service. | FALSE |
+| `mqtt_host` | Host address bound to the MQTT service. | 127.0.0.1 |
+| `mqtt_port` | Port bound to the MQTT service. | 1883 |
+| `mqtt_handler_pool_size` | Thread pool size for processing MQTT messages. | 1 |
+| **`mqtt_payload_formatter`** | **Formatting method for MQTT message payloads. ****Options: `json` (tree model), `line` (table model).** | **json** |
+| `mqtt_max_message_size` | Maximum allowed MQTT message size (bytes). | 1048576 |
## 4. Coding Examples
The following is an example which a mqtt client send messages to IoTDB server.
@@ -102,10 +101,41 @@ connection.disconnect();
## 5. Customize your MQTT Message Format
-If you do not like the above Json format, you can customize your MQTT Message format by just writing several lines
-of codes. An example can be found in [example/mqtt-customize](https://github.com/apache/iotdb/tree/master/example/mqtt-customize) project.
+In a production environment, each device typically has its own MQTT client, and the message formats of these clients have been pre-defined. If communication is to be carried out in accordance with the MQTT message format supported by IoTDB, a comprehensive upgrade and transformation of all existing clients would be required, which would undoubtedly incur significant costs. However, we can easily achieve customization of the MQTT message format through simple programming means, without the need to modify the clients.
+An example can be found in [example/mqtt-customize](https://github.com/apache/iotdb/tree/rc/2.0.1/example/mqtt-customize) project.
+
+Assuming the MQTT client sends the following message format:
+```json
+ {
+ "time":1586076045523,
+ "deviceID":"car_1",
+ "deviceType":"Gasoline car",
+ "point":"Fuel level",
+ "value":10.0
+}
+```
+Or in the form of an array of JSON:
+```java
+[
+ {
+ "time":1586076045523,
+ "deviceID":"car_1",
+ "deviceType":"Gasoline car",
+ "point":"Fuel level",
+ "value":10.0
+ },
+ {
+ "time":1586076045524,
+ "deviceID":"car_2",
+ "deviceType":"NEV(new enegry vehicle)",
+ "point":"Speed",
+ "value":80.0
+ }
+]
+```
+
+Then you can set up the custom MQTT message format through the following steps:
-Steps:
1. Create a java project, and add dependency:
```xml
@@ -120,44 +150,115 @@ e.g.,
```java
package org.apache.iotdb.mqtt.server;
-import io.netty.buffer.ByteBuf;
import org.apache.iotdb.db.protocol.mqtt.Message;
import org.apache.iotdb.db.protocol.mqtt.PayloadFormatter;
+import org.apache.iotdb.db.protocol.mqtt.TableMessage;
+
+import com.google.common.collect.Lists;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import io.netty.buffer.ByteBuf;
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.tsfile.enums.TSDataType;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+/**
+ * The Customized JSON payload formatter. one json format supported: { "time":1586076045523,
+ * "deviceID":"car_1", "deviceType":"NEV", "point":"Speed", "value":80.0 }
+ */
public class CustomizedJsonPayloadFormatter implements PayloadFormatter {
+ private static final String JSON_KEY_TIME = "time";
+ private static final String JSON_KEY_DEVICEID = "deviceID";
+ private static final String JSON_KEY_DEVICETYPE = "deviceType";
+ private static final String JSON_KEY_POINT = "point";
+ private static final String JSON_KEY_VALUE = "value";
+ private static final Gson GSON = new GsonBuilder().create();
@Override
public List format(String topic, ByteBuf payload) {
- // Suppose the payload is a json format
if (payload == null) {
- return null;
+ return new ArrayList<>();
}
-
- String json = payload.toString(StandardCharsets.UTF_8);
- // parse data from the json and generate Messages and put them into List ret
- List ret = new ArrayList<>();
- // this is just an example, so we just generate some Messages directly
- for (int i = 0; i < 2; i++) {
- long ts = i;
- Message message = new Message();
- message.setDevice("d" + i);
- message.setTimestamp(ts);
- message.setMeasurements(Arrays.asList("s1", "s2"));
- message.setValues(Arrays.asList("4.0" + i, "5.0" + i));
- ret.add(message);
+ String txt = payload.toString(StandardCharsets.UTF_8);
+ JsonElement jsonElement = GSON.fromJson(txt, JsonElement.class);
+ if (jsonElement.isJsonObject()) {
+ JsonObject jsonObject = jsonElement.getAsJsonObject();
+ return formatTableRow(topic, jsonObject);
+ } else if (jsonElement.isJsonArray()) {
+ JsonArray jsonArray = jsonElement.getAsJsonArray();
+ List messages = new ArrayList<>();
+ for (JsonElement element : jsonArray) {
+ JsonObject jsonObject = element.getAsJsonObject();
+ messages.addAll(formatTableRow(topic, jsonObject));
+ }
+ return messages;
}
- return ret;
+ throw new JsonParseException("payload is invalidate");
+ }
+
+ @Override
+ @Deprecated
+ public List format(ByteBuf payload) {
+ throw new NotImplementedException();
+ }
+
+ private List formatTableRow(String topic, JsonObject jsonObject) {
+ TableMessage message = new TableMessage();
+ String database = !topic.contains("/") ? topic : topic.substring(0, topic.indexOf("/"));
+ String table = "test_table";
+
+ // Parsing Database Name
+ message.setDatabase((database));
+
+ // Parsing Table Name
+ message.setTable(table);
+
+ // Parsing Tags
+ List tagKeys = new ArrayList<>();
+ tagKeys.add(JSON_KEY_DEVICEID);
+ List