6.9 KiB
6.9 KiB
无人机机场 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 数据订阅
// 订阅机场 OSD topic
final stationTopic = 'thing/product/$gatewaySn/osd';
// 监听数据流
_subscription = _dataSource.stationOsdStream.listen((osd) {
setState(() {
_currentOsd = osd;
_parseOsdFields(osd); // 解析并更新 UI
});
});
2. 数据解析
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 实现左右滑动:
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)
📊 数据映射规则
降雨量格式化
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';
}
电量颜色规则
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); // 红色
}
🔄 生命周期管理
启动监听
@override
void initState() {
super.initState();
_startListening(); // 开始监听 MQTT
}
停止监听
@override
void dispose() {
_stopListening(); // 取消订阅,释放资源
super.dispose();
}
动态更新
@override
void didUpdateWidget(DroneStationOsdCard oldWidget) {
super.didUpdateWidget(oldWidget);
// gatewaySn 或 isOnline 变化时重新订阅
if (oldWidget.gatewaySn != widget.gatewaySn ||
oldWidget.isOnline != widget.isOnline) {
_stopListening();
_startListening();
}
}
🚀 使用方法
在详情页中集成
DroneStationOsdCard(
gatewaySn: widget.station.gatewaySn,
isOnline: detail.isOnline,
)
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
gatewaySn |
String | 机场网关序列号(用于 MQTT topic) |
isOnline |
bool | 机场是否在线(决定是否显示实时数据) |
📝 扩展建议
1. 添加更多 OSD 字段
在 _parseOsdFields 方法中添加新字段:
{
'icon': Icons.new_icon,
'label': '新字段名称',
'value': data['newField'] != null ? '${data['newField']}' : '未知',
'color': const Color(0xFF165DFF),
},
2. 自定义滑动方向
修改 PageView 的 scrollDirection:
PageView.builder(
scrollDirection: Axis.vertical, // 改为上下滑动
// ...
)
3. 自动轮播
添加定时器自动切换卡片:
Timer.periodic(Duration(seconds: 3), (timer) {
if (_osdFields.isNotEmpty) {
setState(() {
_currentIndex = (_currentIndex + 1) % _osdFields.length;
});
_pageController.animateToPage(_currentIndex, ...);
}
});
4. 手势优化
添加双击放大、长按复制等功能:
GestureDetector(
onDoubleTap: () {
// 双击放大
},
onLongPress: () {
// 长按复制数值
Clipboard.setData(ClipboardData(text: field['value']));
},
child: _buildOsdPage(field, index),
)
⚠️ 注意事项
- MQTT 连接:确保应用已连接到 MQTT 服务器
- topic 格式:必须为
thing/product/${gatewaySn}/osd - 数据格式:MQTT 消息 payload 必须是 JSON 格式
- 内存管理:页面销毁时必须取消订阅,避免内存泄漏
- 在线判断:只有机场在线时才订阅 MQTT,离线时不订阅
🐛 调试技巧
查看 MQTT 日志
debugPrint('🔊 [DroneStationOsdCard] 开始监听机场 OSD: ${widget.gatewaySn}');
debugPrint('✅ [DroneStationOsdCard] 收到机场 OSD 数据');
检查数据解析
debugPrint('📊 [DroneStationOsdCard] OSD 原始数据: ${osd.rawData}');
debugPrint('📊 [DroneStationOsdCard] 解析后字段数: ${_osdFields.length}');
📦 依赖项
flutter_bloc: 状态管理mqtt_client: MQTT 通信equatable: 实体类比较get_it: 依赖注入
✅ 完成清单
- 创建
DroneStationOsdCard组件 - 实现 MQTT 数据订阅
- 实现滑动窗口 UI
- 实现数据解析和格式化
- 集成到详情页
- 添加状态管理(在线/离线/加载中)
- 添加生命周期管理
- 添加调试日志