feat: Add Packet Log Screen for BLE packet logging and exporting

- Implemented PacketLogScreen to display and filter BLE packet logs.
- Added functionality to export logs as CSV and text files.
- Introduced clipboard copy feature for hex data.
- Implemented clear logs functionality with confirmation dialog.
- Enhanced MeshCoreBleService to log TX and RX packets with descriptions.
- Added BufferReader methods for reading unsigned and signed 16-bit integers (big-endian).
- Updated CayenneLppParser to read values as big-endian.
- Created MessageStorageService for persisting messages to local storage.
- Enhanced map markers to display telemetry data including voltage, humidity, and pressure.
This commit is contained in:
Janez T
2025-10-14 15:27:18 +02:00
parent ccec842672
commit 59de627289
20 changed files with 4960 additions and 153 deletions

View File

@@ -9,6 +9,8 @@ import 'map_tab.dart';
import 'map_management_screen.dart';
import 'settings_screen.dart';
import 'device_config_screen.dart';
import 'packet_log_screen.dart';
import 'message_history_screen.dart';
class HomeScreen extends StatefulWidget {
final Function(AppThemeMode) onThemeChanged;
@@ -231,6 +233,25 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
PopupMenuButton(
icon: const Icon(Icons.more_vert),
itemBuilder: (context) => [
PopupMenuItem(
child: const Row(
children: [
Icon(Icons.history),
SizedBox(width: 8),
Text('Message History'),
],
),
onTap: () {
Future.delayed(Duration.zero, () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MessageHistoryScreen(),
),
);
});
},
),
PopupMenuItem(
child: const Row(
children: [
@@ -440,21 +461,34 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
),
const SizedBox(width: 8),
// Disconnect button (prominent, icon only)
FilledButton(
onPressed: () async {
await provider.disconnect();
if (context.mounted) {
context.read<AppProvider>().clearAllData();
}
// Long press to open packet log viewer
GestureDetector(
onLongPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PacketLogScreen(
bleService: provider.bleService,
),
),
);
},
style: FilledButton.styleFrom(
backgroundColor: Colors.red.shade700,
foregroundColor: Colors.white,
padding: const EdgeInsets.all(10),
minimumSize: const Size(40, 40),
shape: const CircleBorder(),
child: FilledButton(
onPressed: () async {
await provider.disconnect();
if (context.mounted) {
context.read<AppProvider>().clearAllData();
}
},
style: FilledButton.styleFrom(
backgroundColor: Colors.red.shade700,
foregroundColor: Colors.white,
padding: const EdgeInsets.all(10),
minimumSize: const Size(40, 40),
shape: const CircleBorder(),
),
child: const Icon(Icons.power_settings_new, size: 20),
),
child: const Icon(Icons.power_settings_new, size: 20),
),
],
),