This commit is contained in:
孙小云 2026-01-28 14:13:45 +08:00
parent bbda3b541d
commit a7b3fa2ee2
3 changed files with 273 additions and 1 deletions

View File

@ -0,0 +1,202 @@
# DJI MQTT 模块使用说明(支持多客户端)
## 概述
本模块实现了大疆MQTT消息的接收和处理功能支持动态创建多个MQTT客户端每个客户端可以连接到不同的服务器。
## 核心特性
**多客户端支持** - 可以同时创建多个MQTT客户端
**动态配置** - 每个客户端可以独立配置IP、端口、用户名等
**独立消息处理** - 每个客户端有独立的消息处理器
**共享订阅可选** - 支持开启/关闭共享订阅
**完整数据模型** - 包含所有无人机和机场字段
**自动区分设备** - 自动识别无人机和机场数据
## 架构设计
```
DjiMqttClientManager (管理器)
DjiMqttClientService (客户端实例)
DjiMqttMessageHandler (消息处理器)
IDroneDataCallback / IDockDataCallback (回调接口)
```
## 快速开始
### 1. 注入管理器
```java
@Autowired
private DjiMqttClientManager clientManager;
```
### 2. 创建客户端
```java
// 构建配置
DjiMqttClientConfig config = DjiMqttClientConfig.builder()
.host("mqtt.t-aaron.com") // MQTT服务器地址
.port(10883) // 端口
.clientId("my_client_1") // 客户端ID必须唯一
.username("admin") // 用户名
.password("admin") // 密码
.useSharedSubscription(true) // 是否使用共享订阅
.sharedGroupName("dji-group") // 共享订阅组名
.build();
// 创建并连接客户端
String clientId = clientManager.createClient(config);
```
### 3. 注册回调
```java
// 获取消息处理器
DjiMqttMessageHandler handler = clientManager.getHandler(clientId);
// 注册无人机数据回调
handler.registerDroneDataCallback(droneData -> {
System.out.println("无人机SN: " + droneData.getDeviceSn());
System.out.println("位置: " + droneData.getLatitude() + ", " + droneData.getLongitude());
});
// 注册机场数据回调
handler.registerDockDataCallback(dockData -> {
System.out.println("机场SN: " + dockData.getDeviceSn());
System.out.println("温度: " + dockData.getTemperature());
});
```
## 多客户端示例
### 场景同时连接多个MQTT服务器
```java
@Component
public class MyMqttService {
@Autowired
private DjiMqttClientManager clientManager;
public void init() {
// 客户端1连接到服务器A
DjiMqttClientConfig config1 = DjiMqttClientConfig.builder()
.host("mqtt.server-a.com")
.port(10883)
.clientId("client_a")
.username("admin")
.password("admin")
.useSharedSubscription(true)
.build();
String clientId1 = clientManager.createClient(config1);
DjiMqttMessageHandler handler1 = clientManager.getHandler(clientId1);
handler1.registerDroneDataCallback(data -> processServerA(data));
// 客户端2连接到服务器B
DjiMqttClientConfig config2 = DjiMqttClientConfig.builder()
.host("mqtt.server-b.com")
.port(1883)
.clientId("client_b")
.username("user2")
.password("pass2")
.useSharedSubscription(false)
.build();
String clientId2 = clientManager.createClient(config2);
DjiMqttMessageHandler handler2 = clientManager.getHandler(clientId2);
handler2.registerDroneDataCallback(data -> processServerB(data));
}
}
```
## 管理器API
### 创建客户端
```java
String clientId = clientManager.createClient(config);
```
### 获取消息处理器
```java
DjiMqttMessageHandler handler = clientManager.getHandler(clientId);
```
### 获取客户端
```java
DjiMqttClientService client = clientManager.getClient(clientId);
boolean isConnected = client.isConnected();
```
### 移除客户端
```java
clientManager.removeClient(clientId);
```
### 断开所有客户端
```java
clientManager.disconnectAll();
```
### 获取所有客户端ID
```java
Set<String> clientIds = clientManager.getAllClientIds();
```
## 配置参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| host | String | 是 | - | MQTT服务器地址 |
| port | Integer | 是 | - | MQTT服务器端口 |
| clientId | String | 是 | - | 客户端ID必须唯一 |
| username | String | 是 | - | 用户名 |
| password | String | 是 | - | 密码 |
| connectionTimeout | Integer | 否 | 30 | 连接超时时间(秒) |
| keepAliveInterval | Integer | 否 | 60 | 保持连接时间(秒) |
| autoReconnect | Boolean | 否 | true | 自动重连 |
| cleanSession | Boolean | 否 | false | 清除会话 |
| useSharedSubscription | Boolean | 否 | true | 是否使用共享订阅 |
| sharedGroupName | String | 否 | dji-group | 共享订阅组名 |
## 数据模型
### DroneData无人机数据
包含100+字段,主要分类:
- **基础信息**:固件版本、飞行器状态、档位等
- **位置信息**经纬度、高度、Home点等
- **姿态信息**:偏航角、横滚角、俯仰角
- **速度信息**:水平速度、垂直速度、风速
- **电池信息**:电量、剩余飞行时间、电池详情
- **相机信息**:拍照录像状态、变焦、红外测温等
- **避障信息**:水平/上视/下视避障状态
- **保养信息**:保养状态、累计飞行时间/架次
### DockData机场数据
包含60+字段,主要分类:
- **基础信息**:固件版本、机场状态、任务状态
- **位置信息**:经纬度、高度、朝向角
- **环境信息**:温度、湿度、风速、降雨量
- **设备状态**:舱盖状态、飞行器在舱状态、补光灯等
- **电池信息**:充电状态、备用电池、电池保养
- **网络信息**:网络类型、质量、速率
- **图传信息**4G/SDR链路状态、信号质量
## 注意事项
1. **clientId必须唯一**每个MQTT客户端的clientId必须全局唯一
2. **部分字段推送**每次MQTT消息可能只包含部分字段使用时需要判空
3. **原始数据访问**:所有字段都保存在`rawData`中可以通过Map访问
4. **共享订阅**:多实例部署时建议开启共享订阅,避免重复消费
5. **独立处理器**:每个客户端有独立的消息处理器,互不影响
6. **自动重连**:连接断开后会自动重连(可配置)
## 完整示例
参考 `DjiMqttUsageExample.java` 获取完整示例代码。

View File

@ -1,4 +1,4 @@
package com.ruoyi.device.domain.impl.djimqtt.config; package com.ruoyi.device.service.config;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;

View File

@ -0,0 +1,70 @@
package com.ruoyi.device.service.impl;
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.config.DjiMqttClientConfig;
import com.ruoyi.device.service.config.DjiMqttProperties;
import com.ruoyi.device.domain.impl.djimqtt.handler.DjiMqttMessageHandler;
import com.ruoyi.device.domain.impl.djimqtt.manager.DjiMqttClientManager;
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.Service;
@Service
@Slf4j
public class DjiService {
@Autowired
private DjiMqttClientManager clientManager;
@Autowired
private DjiMqttProperties mqttProperties;
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReady() {
// 从配置文件读取配置
DjiMqttClientConfig config = DjiMqttClientConfig.builder()
.host(mqttProperties.getHost())
.port(mqttProperties.getPort())
.clientId(mqttProperties.getClientId())
.username(mqttProperties.getUsername())
.password(mqttProperties.getPassword())
.connectionTimeout(mqttProperties.getConnectionTimeout())
.keepAliveInterval(mqttProperties.getKeepAliveInterval())
.autoReconnect(mqttProperties.getAutoReconnect())
.cleanSession(mqttProperties.getCleanSession())
.useSharedSubscription(true)
.sharedGroupName("dji-group")
.build();
// 创建客户端
String clientId = clientManager.createClient(config);
// 获取消息处理器
DjiMqttMessageHandler handler = clientManager.getHandler(clientId);
// 注册无人机数据回调
handler.registerDroneDataCallback(new IDroneDataCallback() {
@Override
public void onDroneData(DroneData droneData) {
log.info("droneData:{}", droneData);
}
});
// 注册机场数据回调
handler.registerDockDataCallback(new IDockDataCallback() {
@Override
public void onDockData(DockData dockData) {
log.info("droneData:{}", dockData);
}
});
log.info("客户端已创建并注册回调");
}
}