297 lines
6.9 KiB
Markdown
297 lines
6.9 KiB
Markdown
# 无人机机场 OSD 实时数据展示功能
|
||
|
||
## 📋 功能概述
|
||
|
||
在无人机机场详情页面添加了 **OSD 实时数据卡片**,通过 MQTT 订阅 `thing/product/${gatewaySn}/osd` topic,实时展示机场的遥测数据。
|
||
|
||
## 🎯 核心特性
|
||
|
||
### 1. 滑动窗口设计
|
||
- **左右滑动切换**:用户可以左右滑动查看不同的 OSD 数据字段
|
||
- **底部指示器**:显示当前页码和总页数
|
||
- **滑动提示**:左右箭头提示用户可以滑动
|
||
|
||
### 2. 智能状态管理
|
||
- **在线时**:显示实时 OSD 数据(电量、温度、风速等)
|
||
- **离线时**:显示"机场离线,暂无实时数据"提示
|
||
- **加载中**:显示加载动画
|
||
|
||
### 3. 数据字段展示
|
||
|
||
目前展示的 OSD 字段包括:
|
||
|
||
| 字段 | 图标 | 颜色规则 | 示例值 |
|
||
|------|------|---------|--------|
|
||
| 电量 | 🔋 battery_full | >50% 绿色, 20-50% 橙色, <20% 红色 | 85% |
|
||
| 温度 | 🌡️ thermostat | 蓝色 | 25°C |
|
||
| 风速 | 💨 air | 绿色 | 3.5 m/s |
|
||
| 降雨量 | 💧 water_drop | 蓝色 | 小雨 / 12 mm |
|
||
| 网络状态 | 📶 network_check | 灰色 | 等级 4 |
|
||
| GPS | 🛰️ gps_fixed | 紫色 | 12 颗 |
|
||
|
||
## 📁 文件结构
|
||
|
||
```
|
||
lib/features/v2/device_list/
|
||
├── presentation/
|
||
│ ├── pages/
|
||
│ │ └── drone_station_detail_page.dart # 详情页(集成 OSD 卡片)
|
||
│ └── widgets/
|
||
│ └── drone_station_osd_card.dart # OSD 实时数据卡片组件
|
||
```
|
||
|
||
## 🔧 技术实现
|
||
|
||
### 1. MQTT 数据订阅
|
||
|
||
```dart
|
||
// 订阅机场 OSD topic
|
||
final stationTopic = 'thing/product/$gatewaySn/osd';
|
||
|
||
// 监听数据流
|
||
_subscription = _dataSource.stationOsdStream.listen((osd) {
|
||
setState(() {
|
||
_currentOsd = osd;
|
||
_parseOsdFields(osd); // 解析并更新 UI
|
||
});
|
||
});
|
||
```
|
||
|
||
### 2. 数据解析
|
||
|
||
```dart
|
||
void _parseOsdFields(DroneOsdEntity osd) {
|
||
final data = osd.rawData;
|
||
|
||
_osdFields = [
|
||
{
|
||
'icon': Icons.battery_full_rounded,
|
||
'label': '电量',
|
||
'value': data['battery'] != null ? '${data['battery']}%' : '未知',
|
||
'color': _getBatteryColor(data['battery']),
|
||
},
|
||
// ... 其他字段
|
||
];
|
||
}
|
||
```
|
||
|
||
### 3. 滑动卡片实现
|
||
|
||
使用 `PageView.builder` 实现左右滑动:
|
||
|
||
```dart
|
||
PageView.builder(
|
||
itemCount: _osdFields.length,
|
||
onPageChanged: (index) {
|
||
setState(() {
|
||
_currentIndex = index;
|
||
});
|
||
},
|
||
itemBuilder: (context, index) {
|
||
final field = _osdFields[index];
|
||
return _buildOsdPage(field, index);
|
||
},
|
||
)
|
||
```
|
||
|
||
## 🎨 UI 设计
|
||
|
||
### 卡片布局
|
||
```
|
||
┌─────────────────────────────┐
|
||
│ [图标] 电量 ◀ ▶ │
|
||
│ │
|
||
│ 85% │
|
||
│ │
|
||
│ 1 / 6 │
|
||
│ │
|
||
│ ● ○ ○ ○ ○ ○ │
|
||
└─────────────────────────────┘
|
||
```
|
||
|
||
### 状态指示器
|
||
- **当前页**:长条蓝色圆点(16px)
|
||
- **其他页**:短条灰色圆点(6px)
|
||
|
||
## 📊 数据映射规则
|
||
|
||
### 降雨量格式化
|
||
|
||
```dart
|
||
String _formatRainfall(dynamic rainfall) {
|
||
if (rainfall is String) {
|
||
switch (rainfall.toLowerCase()) {
|
||
case 'no_rain': return '无降雨';
|
||
case 'light_rain': return '小雨';
|
||
case 'moderate_rain': return '中雨';
|
||
case 'heavy_rain': return '大雨';
|
||
default: return '$rainfall mm';
|
||
}
|
||
}
|
||
return '$rainfall mm';
|
||
}
|
||
```
|
||
|
||
### 电量颜色规则
|
||
|
||
```dart
|
||
Color _getBatteryColor(dynamic battery) {
|
||
final value = battery is num ? battery.toDouble() : 0.0;
|
||
if (value > 50) return Color(0xFF00B42A); // 绿色
|
||
if (value > 20) return Color(0xFFFF7D00); // 橙色
|
||
return Color(0xFFF53F3F); // 红色
|
||
}
|
||
```
|
||
|
||
## 🔄 生命周期管理
|
||
|
||
### 启动监听
|
||
```dart
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_startListening(); // 开始监听 MQTT
|
||
}
|
||
```
|
||
|
||
### 停止监听
|
||
```dart
|
||
@override
|
||
void dispose() {
|
||
_stopListening(); // 取消订阅,释放资源
|
||
super.dispose();
|
||
}
|
||
```
|
||
|
||
### 动态更新
|
||
```dart
|
||
@override
|
||
void didUpdateWidget(DroneStationOsdCard oldWidget) {
|
||
super.didUpdateWidget(oldWidget);
|
||
// gatewaySn 或 isOnline 变化时重新订阅
|
||
if (oldWidget.gatewaySn != widget.gatewaySn ||
|
||
oldWidget.isOnline != widget.isOnline) {
|
||
_stopListening();
|
||
_startListening();
|
||
}
|
||
}
|
||
```
|
||
|
||
## 🚀 使用方法
|
||
|
||
### 在详情页中集成
|
||
|
||
```dart
|
||
DroneStationOsdCard(
|
||
gatewaySn: widget.station.gatewaySn,
|
||
isOnline: detail.isOnline,
|
||
)
|
||
```
|
||
|
||
### 参数说明
|
||
|
||
| 参数 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `gatewaySn` | String | 机场网关序列号(用于 MQTT topic) |
|
||
| `isOnline` | bool | 机场是否在线(决定是否显示实时数据) |
|
||
|
||
## 📝 扩展建议
|
||
|
||
### 1. 添加更多 OSD 字段
|
||
|
||
在 `_parseOsdFields` 方法中添加新字段:
|
||
|
||
```dart
|
||
{
|
||
'icon': Icons.new_icon,
|
||
'label': '新字段名称',
|
||
'value': data['newField'] != null ? '${data['newField']}' : '未知',
|
||
'color': const Color(0xFF165DFF),
|
||
},
|
||
```
|
||
|
||
### 2. 自定义滑动方向
|
||
|
||
修改 `PageView` 的 `scrollDirection`:
|
||
|
||
```dart
|
||
PageView.builder(
|
||
scrollDirection: Axis.vertical, // 改为上下滑动
|
||
// ...
|
||
)
|
||
```
|
||
|
||
### 3. 自动轮播
|
||
|
||
添加定时器自动切换卡片:
|
||
|
||
```dart
|
||
Timer.periodic(Duration(seconds: 3), (timer) {
|
||
if (_osdFields.isNotEmpty) {
|
||
setState(() {
|
||
_currentIndex = (_currentIndex + 1) % _osdFields.length;
|
||
});
|
||
_pageController.animateToPage(_currentIndex, ...);
|
||
}
|
||
});
|
||
```
|
||
|
||
### 4. 手势优化
|
||
|
||
添加双击放大、长按复制等功能:
|
||
|
||
```dart
|
||
GestureDetector(
|
||
onDoubleTap: () {
|
||
// 双击放大
|
||
},
|
||
onLongPress: () {
|
||
// 长按复制数值
|
||
Clipboard.setData(ClipboardData(text: field['value']));
|
||
},
|
||
child: _buildOsdPage(field, index),
|
||
)
|
||
```
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
1. **MQTT 连接**:确保应用已连接到 MQTT 服务器
|
||
2. **topic 格式**:必须为 `thing/product/${gatewaySn}/osd`
|
||
3. **数据格式**:MQTT 消息 payload 必须是 JSON 格式
|
||
4. **内存管理**:页面销毁时必须取消订阅,避免内存泄漏
|
||
5. **在线判断**:只有机场在线时才订阅 MQTT,离线时不订阅
|
||
|
||
## 🐛 调试技巧
|
||
|
||
### 查看 MQTT 日志
|
||
|
||
```dart
|
||
debugPrint('🔊 [DroneStationOsdCard] 开始监听机场 OSD: ${widget.gatewaySn}');
|
||
debugPrint('✅ [DroneStationOsdCard] 收到机场 OSD 数据');
|
||
```
|
||
|
||
### 检查数据解析
|
||
|
||
```dart
|
||
debugPrint('📊 [DroneStationOsdCard] OSD 原始数据: ${osd.rawData}');
|
||
debugPrint('📊 [DroneStationOsdCard] 解析后字段数: ${_osdFields.length}');
|
||
```
|
||
|
||
## 📦 依赖项
|
||
|
||
- `flutter_bloc`: 状态管理
|
||
- `mqtt_client`: MQTT 通信
|
||
- `equatable`: 实体类比较
|
||
- `get_it`: 依赖注入
|
||
|
||
## ✅ 完成清单
|
||
|
||
- [x] 创建 `DroneStationOsdCard` 组件
|
||
- [x] 实现 MQTT 数据订阅
|
||
- [x] 实现滑动窗口 UI
|
||
- [x] 实现数据解析和格式化
|
||
- [x] 集成到详情页
|
||
- [x] 添加状态管理(在线/离线/加载中)
|
||
- [x] 添加生命周期管理
|
||
- [x] 添加调试日志
|