Add Debug page and fix BLE communication issues

Major changes:
- Added Debug tab with real-time message logging and hex viewer
- Implemented timed data logging ($UMTDL command) per API v1.3
- Fixed BLE message parsing to handle notifications without line endings
- Added Schema 2 support (22-field timed logging packets)
- Updated Maglink BLE UUIDs (fff0/fff1/fff2)
- Added connection timeout (10s) to prevent hanging on unavailable devices
- Added connection status display and manual push-button logging trigger
- Improved retry logging with attempt numbers and delays
- Added console window allocation for Windows debug output
- Added BLE disconnect on app close

Bug fixes:
- Fixed device name filtering for Maglink (ML-* prefix)
- Fixed RtkGps enum reference in DeviceScanViewModel
- Fixed DebugMessage namespace (moved to Models)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
brentperteet
2026-07-06 17:32:00 -05:00
parent b602b762c9
commit 299ec3875d
19 changed files with 608 additions and 27 deletions

View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:FieldLogger.ViewModels"
xmlns:models="clr-namespace:FieldLogger.Models"
x:Class="FieldLogger.Views.DebugPage"
x:DataType="vm:DebugViewModel"
Title="Debug">
<ScrollView>
<VerticalStackLayout Padding="16" Spacing="12">
<Label Text="Connection Status" FontAttributes="Bold" FontSize="16" />
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}" StrokeShape="RoundRectangle 12" Padding="12">
<VerticalStackLayout Spacing="10">
<Grid ColumnDefinitions="16,*,Auto" ColumnSpacing="8">
<Ellipse Grid.Column="0" WidthRequest="12" HeightRequest="12" VerticalOptions="Center"
Fill="{Binding ConnectionStateColor}" />
<Label Grid.Column="1" Text="{Binding ConnectionStatus}" VerticalOptions="Center" />
<Button Grid.Column="2" Text="Enable Push-Button" FontSize="12" Padding="10,4"
Command="{Binding EnablePushButtonLoggingCommand}"
IsEnabled="{Binding IsConnected}" />
</Grid>
</VerticalStackLayout>
</Border>
<Label Text="Timed Data Logging" FontAttributes="Bold" FontSize="16" Margin="0,12,0,0" />
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}" StrokeShape="RoundRectangle 12" Padding="12">
<VerticalStackLayout Spacing="10">
<Label Text="Enable continuous data streaming from UM Receiver" FontSize="12" TextColor="Gray" />
<Grid ColumnDefinitions="Auto,*" ColumnSpacing="12">
<Switch Grid.Column="0" IsToggled="{Binding IsTimedLoggingEnabled}" IsEnabled="{Binding IsConnected}" />
<Label Grid.Column="1" Text="{Binding TimedLoggingStatus}" VerticalOptions="Center" />
</Grid>
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="8" IsVisible="{Binding IsTimedLoggingEnabled}">
<Label Grid.Column="0" Text="{Binding LogPeriodLabel}" VerticalOptions="Center" FontSize="14" />
<Stepper Grid.Column="1" Minimum="10" Maximum="100" Increment="10" Value="{Binding LogPeriod}" />
</Grid>
</VerticalStackLayout>
</Border>
<Label Text="Message Log" FontAttributes="Bold" FontSize="16" Margin="0,12,0,0" />
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}" StrokeShape="RoundRectangle 12" Padding="12">
<VerticalStackLayout Spacing="10">
<Grid ColumnDefinitions="*,Auto,Auto,Auto" ColumnSpacing="8">
<Label Grid.Column="0" Text="{Binding MessageCount, StringFormat='{0} messages'}" VerticalOptions="Center" FontSize="12" TextColor="Gray" />
<Label Grid.Column="1" Text="Show Hex" VerticalOptions="Center" FontSize="12" TextColor="Gray" />
<Switch Grid.Column="2" IsToggled="{Binding ShowHex}" />
<Button Grid.Column="3" Text="Clear" FontSize="12" Padding="10,4" Command="{Binding ClearMessagesCommand}" />
</Grid>
<BoxView HeightRequest="1" Color="{AppThemeBinding Light=#E0E0E0, Dark=#333}" />
<CollectionView ItemsSource="{Binding Messages}" HeightRequest="400">
<CollectionView.EmptyView>
<Label Text="No messages yet. Messages will appear here when received from the device."
TextColor="Gray" FontSize="12" HorizontalOptions="Center" VerticalOptions="Center" />
</CollectionView.EmptyView>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:DebugMessage">
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#FFFFFF, Dark=#2C2C2E}"
StrokeShape="RoundRectangle 8" Padding="8" Margin="0,2">
<VerticalStackLayout Spacing="4">
<Grid ColumnDefinitions="Auto,*,Auto" ColumnSpacing="8">
<Label Grid.Column="0" Text="{Binding Timestamp, StringFormat='{0:HH:mm:ss.fff}'}"
FontSize="10" TextColor="Gray" FontFamily="Courier" />
<Label Grid.Column="1" Text="{Binding Type}"
FontSize="10" FontAttributes="Bold" TextColor="{Binding TypeColor}" />
<Label Grid.Column="2" Text="{Binding Direction}"
FontSize="10" TextColor="Gray" />
</Grid>
<Label Text="{Binding RawMessage}" FontSize="11" FontFamily="Courier" />
<Label Text="{Binding HexBytes}" FontSize="9" TextColor="DarkGray" FontFamily="Courier"
IsVisible="{Binding Source={RelativeSource AncestorType={x:Type vm:DebugViewModel}}, Path=ShowHex}" />
<Label Text="{Binding ParsedData}" FontSize="10" TextColor="Gray"
IsVisible="{Binding HasParsedData}" />
</VerticalStackLayout>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</Border>
</VerticalStackLayout>
</ScrollView>
</ContentPage>