diff --git a/pom.xml b/pom.xml
index ea47435..b6a0a18 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,6 +105,13 @@
provided
+
+
+ org.eclipse.paho
+ org.eclipse.paho.client.mqttv3
+ 1.2.5
+
+
diff --git a/src/main/java/com/ruoyi/device/domain/impl/djimqtt/README.md b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/README.md
new file mode 100644
index 0000000..bd935c8
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/README.md
@@ -0,0 +1,120 @@
+# DJI MQTT 模块使用说明
+
+## 概述
+
+本模块实现了大疆MQTT消息的接收和处理功能,采用共享订阅方式,支持多实例部署。
+
+## 功能特性
+
+- ✅ 自动连接和重连
+- ✅ 共享订阅(多实例部署时只有一个实例消费消息)
+- ✅ 自动区分无人机和机场数据
+- ✅ 回调接口设计,使用者无需关心osd和state的区别
+- ✅ 完整的数据模型定义
+- ✅ 原始数据保留(rawData字段)
+
+## 架构设计
+
+```
+DjiMqttClientService (MQTT客户端)
+ ↓
+DjiMqttMessageHandler (消息处理器)
+ ↓
+IDroneDataCallback / IDockDataCallback (回调接口)
+ ↓
+使用者实现
+```
+
+## 配置说明
+
+在 `bootstrap.yml` 中配置:
+
+```yaml
+dji:
+ mqtt:
+ host: mqtt.t-aaron.com
+ port: 10883
+ version: 5
+ client-id: ThingsBoard_gateway
+ username: admin
+ password: admin
+ connection-timeout: 30
+ keep-alive-interval: 60
+ auto-reconnect: true
+ clean-session: false
+```
+
+## 使用方法
+
+### 1. 注入消息处理器
+
+```java
+@Autowired
+private DjiMqttMessageHandler messageHandler;
+```
+
+### 2. 实现回调接口
+
+```java
+// 无人机数据回调
+messageHandler.registerDroneDataCallback(new IDroneDataCallback() {
+ @Override
+ public void onDroneData(DroneData droneData) {
+ // 处理无人机数据
+ String sn = droneData.getDeviceSn();
+ Double latitude = droneData.getLatitude();
+ Double longitude = droneData.getLongitude();
+
+ // 访问原始数据
+ Map rawData = droneData.getRawData();
+ }
+});
+
+// 机场数据回调
+messageHandler.registerDockDataCallback(new IDockDataCallback() {
+ @Override
+ public void onDockData(DockData dockData) {
+ // 处理机场数据
+ String sn = dockData.getDeviceSn();
+ Integer modeCode = dockData.getModeCode();
+ Float temperature = dockData.getTemperature();
+
+ // 访问原始数据
+ Map rawData = dockData.getRawData();
+ }
+});
+```
+
+## 数据模型
+
+### DroneData(无人机数据)
+
+主要字段:
+- `deviceSn`: 设备SN
+- `messageType`: 消息类型(osd/state)
+- `latitude/longitude`: 位置信息
+- `elevation/height`: 高度信息
+- `modeCode`: 飞行器状态
+- `rawData`: 原始数据(包含所有字段)
+
+### DockData(机场数据)
+
+主要字段:
+- `deviceSn`: 设备SN
+- `messageType`: 消息类型(osd/state)
+- `latitude/longitude`: 位置信息
+- `modeCode`: 机场状态
+- `temperature/humidity`: 环境信息
+- `coverState`: 舱盖状态
+- `rawData`: 原始数据(包含所有字段)
+
+## 注意事项
+
+1. **部分字段推送**:每次MQTT消息可能只包含部分字段,使用时需要判空
+2. **原始数据访问**:所有字段都保存在`rawData`中,可以通过Map访问
+3. **共享订阅**:多实例部署时,同一条消息只会被一个实例消费
+4. **自动重连**:连接断开后会自动重连
+
+## 示例代码
+
+参考 `DjiMqttUsageExample.java` 获取完整示例。
diff --git a/src/main/java/com/ruoyi/device/domain/impl/djimqtt/callback/IDockDataCallback.java b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/callback/IDockDataCallback.java
new file mode 100644
index 0000000..9fb14d6
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/callback/IDockDataCallback.java
@@ -0,0 +1,18 @@
+package com.ruoyi.device.domain.impl.djimqtt.callback;
+
+import com.ruoyi.device.domain.impl.djimqtt.model.DockData;
+
+/**
+ * 机场数据回调接口
+ *
+ * @author ruoyi
+ */
+public interface IDockDataCallback {
+
+ /**
+ * 处理机场数据
+ *
+ * @param dockData 机场数据
+ */
+ void onDockData(DockData dockData);
+}
diff --git a/src/main/java/com/ruoyi/device/domain/impl/djimqtt/callback/IDroneDataCallback.java b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/callback/IDroneDataCallback.java
new file mode 100644
index 0000000..4bb7f74
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/callback/IDroneDataCallback.java
@@ -0,0 +1,18 @@
+package com.ruoyi.device.domain.impl.djimqtt.callback;
+
+import com.ruoyi.device.domain.impl.djimqtt.model.DroneData;
+
+/**
+ * 无人机数据回调接口
+ *
+ * @author ruoyi
+ */
+public interface IDroneDataCallback {
+
+ /**
+ * 处理无人机数据
+ *
+ * @param droneData 无人机数据
+ */
+ void onDroneData(DroneData droneData);
+}
diff --git a/src/main/java/com/ruoyi/device/domain/impl/djimqtt/config/DjiMqttProperties.java b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/config/DjiMqttProperties.java
new file mode 100644
index 0000000..4be0041
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/config/DjiMqttProperties.java
@@ -0,0 +1,66 @@
+package com.ruoyi.device.domain.impl.djimqtt.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * DJI MQTT配置属性
+ *
+ * @author ruoyi
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "dji.mqtt")
+public class DjiMqttProperties {
+
+ /**
+ * MQTT服务器地址
+ */
+ private String host = "mqtt.t-aaron.com";
+
+ /**
+ * MQTT服务器端口
+ */
+ private Integer port = 10883;
+
+ /**
+ * MQTT协议版本
+ */
+ private Integer version = 5;
+
+ /**
+ * 客户端ID
+ */
+ private String clientId = "ThingsBoard_gateway";
+
+ /**
+ * 用户名
+ */
+ private String username = "admin";
+
+ /**
+ * 密码
+ */
+ private String password = "admin";
+
+ /**
+ * 连接超时时间(秒)
+ */
+ private Integer connectionTimeout = 30;
+
+ /**
+ * 保持连接时间(秒)
+ */
+ private Integer keepAliveInterval = 60;
+
+ /**
+ * 自动重连
+ */
+ private Boolean autoReconnect = true;
+
+ /**
+ * 清除会话
+ */
+ private Boolean cleanSession = false;
+}
diff --git a/src/main/java/com/ruoyi/device/domain/impl/djimqtt/example/DjiMqttUsageExample.java b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/example/DjiMqttUsageExample.java
new file mode 100644
index 0000000..9838ea6
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/example/DjiMqttUsageExample.java
@@ -0,0 +1,116 @@
+package com.ruoyi.device.domain.impl.djimqtt.example;
+
+import com.ruoyi.device.domain.impl.djimqtt.callback.IDockDataCallback;
+import com.ruoyi.device.domain.impl.djimqtt.callback.IDroneDataCallback;
+import com.ruoyi.device.domain.impl.djimqtt.handler.DjiMqttMessageHandler;
+import com.ruoyi.device.domain.impl.djimqtt.model.DockData;
+import com.ruoyi.device.domain.impl.djimqtt.model.DroneData;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * DJI MQTT使用示例
+ *
+ * 使用说明:
+ * 1. 注入 DjiMqttMessageHandler
+ * 2. 实现 IDroneDataCallback 或 IDockDataCallback 接口
+ * 3. 在应用启动后注册回调
+ * 4. 在回调方法中处理接收到的数据
+ *
+ * @author ruoyi
+ */
+@Slf4j
+@Component
+public class DjiMqttUsageExample {
+
+ @Autowired
+ private DjiMqttMessageHandler messageHandler;
+
+ /**
+ * 应用启动后注册回调
+ */
+ @EventListener(ApplicationReadyEvent.class)
+ public void registerCallbacks() {
+ // 注册无人机数据回调
+ messageHandler.registerDroneDataCallback(new IDroneDataCallback() {
+ @Override
+ public void onDroneData(DroneData droneData) {
+ handleDroneData(droneData);
+ }
+ });
+
+ // 注册机场数据回调
+ messageHandler.registerDockDataCallback(new IDockDataCallback() {
+ @Override
+ public void onDockData(DockData dockData) {
+ handleDockData(dockData);
+ }
+ });
+
+ log.info("DJI MQTT回调已注册");
+ }
+
+ /**
+ * 处理无人机数据
+ */
+ private void handleDroneData(DroneData droneData) {
+ log.info("收到无人机数据 - SN: {}, Type: {}",
+ droneData.getDeviceSn(),
+ droneData.getMessageType());
+
+ // 示例:处理位置信息
+ if (droneData.getLatitude() != null && droneData.getLongitude() != null) {
+ log.info("无人机位置 - 纬度: {}, 经度: {}, 高度: {}",
+ droneData.getLatitude(),
+ droneData.getLongitude(),
+ droneData.getElevation());
+ }
+
+ // 示例:处理电池信息(从rawData中获取)
+ if (droneData.getRawData() != null && droneData.getRawData().containsKey("battery")) {
+ Object battery = droneData.getRawData().get("battery");
+ log.info("无人机电池信息: {}", battery);
+ }
+
+ // 示例:处理相机信息
+ if (droneData.getRawData() != null && droneData.getRawData().containsKey("cameras")) {
+ Object cameras = droneData.getRawData().get("cameras");
+ log.info("无人机相机信息: {}", cameras);
+ }
+ }
+
+ /**
+ * 处理机场数据
+ */
+ private void handleDockData(DockData dockData) {
+ log.info("收到机场数据 - SN: {}, Type: {}",
+ dockData.getDeviceSn(),
+ dockData.getMessageType());
+
+ // 示例:处理机场状态
+ if (dockData.getModeCode() != null) {
+ log.info("机场状态: {}", dockData.getModeCode());
+ }
+
+ // 示例:处理环境信息
+ if (dockData.getTemperature() != null) {
+ log.info("机场温度: {}°C, 湿度: {}%",
+ dockData.getTemperature(),
+ dockData.getHumidity());
+ }
+
+ // 示例:处理舱盖状态
+ if (dockData.getCoverState() != null) {
+ log.info("舱盖状态: {}", dockData.getCoverState());
+ }
+
+ // 示例:处理飞行器充电状态(从rawData中获取)
+ if (dockData.getRawData() != null && dockData.getRawData().containsKey("drone_charge_state")) {
+ Object chargeState = dockData.getRawData().get("drone_charge_state");
+ log.info("飞行器充电状态: {}", chargeState);
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/device/domain/impl/djimqtt/handler/DjiMqttMessageHandler.java b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/handler/DjiMqttMessageHandler.java
new file mode 100644
index 0000000..e6489c6
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/domain/impl/djimqtt/handler/DjiMqttMessageHandler.java
@@ -0,0 +1,216 @@
+package com.ruoyi.device.domain.impl.djimqtt.handler;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.device.domain.impl.djimqtt.callback.IDockDataCallback;
+import com.ruoyi.device.domain.impl.djimqtt.callback.IDroneDataCallback;
+import com.ruoyi.device.domain.impl.djimqtt.model.DjiMqttMessage;
+import com.ruoyi.device.domain.impl.djimqtt.model.DockData;
+import com.ruoyi.device.domain.impl.djimqtt.model.DroneData;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * DJI MQTT消息处理器
+ *
+ * @author ruoyi
+ */
+@Slf4j
+@Component
+public class DjiMqttMessageHandler {
+
+ private final ObjectMapper objectMapper = new ObjectMapper();
+
+ /**
+ * 无人机数据回调列表
+ */
+ private final List droneDataCallbacks = new ArrayList<>();
+
+ /**
+ * 机场数据回调列表
+ */
+ private final List dockDataCallbacks = new ArrayList<>();
+
+ /**
+ * 无人机SN正则表达式(根据文档示例:1581F6Q8X251C00G04H8)
+ */
+ private static final Pattern DRONE_SN_PATTERN = Pattern.compile("^[0-9A-Z]{20}$");
+
+ /**
+ * 机场SN正则表达式(根据文档示例:7CTXN5K00B0AXM)
+ */
+ private static final Pattern DOCK_SN_PATTERN = Pattern.compile("^[0-9A-Z]{14}$");
+
+ /**
+ * 注册无人机数据回调
+ *
+ * @param callback 回调接口
+ */
+ public void registerDroneDataCallback(IDroneDataCallback callback) {
+ if (callback != null && !droneDataCallbacks.contains(callback)) {
+ droneDataCallbacks.add(callback);
+ log.info("注册无人机数据回调: {}", callback.getClass().getSimpleName());
+ }
+ }
+
+ /**
+ * 注册机场数据回调
+ *
+ * @param callback 回调接口
+ */
+ public void registerDockDataCallback(IDockDataCallback callback) {
+ if (callback != null && !dockDataCallbacks.contains(callback)) {
+ dockDataCallbacks.add(callback);
+ log.info("注册机场数据回调: {}", callback.getClass().getSimpleName());
+ }
+ }
+
+ /**
+ * 处理MQTT消息
+ *
+ * @param topic 主题
+ * @param payload 消息内容
+ */
+ public void handleMessage(String topic, String payload) {
+ try {
+ log.debug("收到MQTT消息 - Topic: {}, Payload: {}", topic, payload);
+
+ // 解析设备SN和消息类型
+ String deviceSn = extractDeviceSnFromTopic(topic);
+ String messageType = extractMessageTypeFromTopic(topic);
+
+ if (deviceSn == null || messageType == null) {
+ log.warn("无法从Topic解析设备SN或消息类型: {}", topic);
+ return;
+ }
+
+ // 解析JSON消息
+ @SuppressWarnings("unchecked")
+ DjiMqttMessage