# 无人机机场 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] 添加调试日志