Initial commit: FieldLogger MAUI app with Maglink BLE support

Added Maglink RTK GNSS receiver integration with correct BLE UUIDs and device name filtering (ML-* prefix).

🤖 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 13:46:50 -05:00
commit b602b762c9
79 changed files with 5807 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
<?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.HomePage"
x:DataType="vm:HomeViewModel"
Title="Field Logger">
<ScrollView>
<VerticalStackLayout Padding="16" Spacing="12">
<!-- Device connection status -->
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}" StrokeShape="RoundRectangle 12" Padding="12">
<Grid ColumnDefinitions="16,*,Auto" RowDefinitions="Auto,Auto" RowSpacing="10" ColumnSpacing="10">
<Ellipse Grid.Row="0" Grid.Column="0" WidthRequest="12" HeightRequest="12" VerticalOptions="Center"
Fill="{Binding Manager.LocatorState, Converter={StaticResource StateColor}}" />
<VerticalStackLayout Grid.Row="0" Grid.Column="1" Spacing="0">
<Label Text="{Binding Manager.LocatorName, TargetNullValue='Locating Receiver — not selected'}" FontAttributes="Bold" />
<Label Text="{Binding Manager.LocatorState, Converter={StaticResource StateText}}" FontSize="12" TextColor="Gray" />
</VerticalStackLayout>
<Button Grid.Row="0" Grid.Column="2" Text="Select" FontSize="12" Padding="10,4"
Command="{Binding SelectLocatorCommand}" />
<Ellipse Grid.Row="1" Grid.Column="0" WidthRequest="12" HeightRequest="12" VerticalOptions="Center"
Fill="{Binding Manager.GpsState, Converter={StaticResource StateColor}}" />
<VerticalStackLayout Grid.Row="1" Grid.Column="1" Spacing="0">
<Label Text="{Binding Manager.GpsName, TargetNullValue='Maglink RTK GPS — not selected'}" FontAttributes="Bold" />
<Label Text="{Binding Manager.GpsState, Converter={StaticResource StateText}}" FontSize="12" TextColor="Gray" />
</VerticalStackLayout>
<Button Grid.Row="1" Grid.Column="2" Text="Select" FontSize="12" Padding="10,4"
Command="{Binding SelectGpsCommand}" />
</Grid>
</Border>
<!-- Live GNSS fix -->
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}" StrokeShape="RoundRectangle 12" Padding="12">
<VerticalStackLayout Spacing="4">
<HorizontalStackLayout Spacing="8">
<Label Text="GPS" FontAttributes="Bold" />
<Label Text="{Binding FixStatusLabel}" TextColor="DodgerBlue" FontAttributes="Bold" />
</HorizontalStackLayout>
<Label Text="{Binding FixSummary}" FontFamily="Courier New" FontSize="13" />
<Label Text="{Binding FixAccuracy}" FontSize="12" TextColor="Gray" />
</VerticalStackLayout>
</Border>
<!-- Active job -->
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}" StrokeShape="RoundRectangle 12" Padding="12">
<VerticalStackLayout Spacing="8">
<Grid ColumnDefinitions="*,Auto">
<VerticalStackLayout Spacing="0">
<Label Text="{Binding ActiveJobName}" FontAttributes="Bold" FontSize="16" />
<Label FontSize="12" TextColor="Gray">
<Label.Text>
<Binding Path="PointCount" StringFormat="{}{0} points logged" />
</Label.Text>
</Label>
</VerticalStackLayout>
<HorizontalStackLayout Grid.Column="1" Spacing="6">
<Button Text="New Job" FontSize="12" Padding="10,4" Command="{Binding NewJobCommand}" />
<Button Text="Jobs" FontSize="12" Padding="10,4" Command="{Binding SelectJobCommand}" />
</HorizontalStackLayout>
</Grid>
<Label Text="Press the log button on the receiver to capture a point."
FontSize="12" TextColor="Gray" IsVisible="{Binding HasActiveJob}" />
</VerticalStackLayout>
</Border>
<!-- Recent points -->
<Label Text="Recent Points" FontAttributes="Bold" Margin="4,8,0,0" />
<CollectionView ItemsSource="{Binding RecentPoints}" HeightRequest="320">
<CollectionView.EmptyView>
<Label Text="No points logged yet." TextColor="Gray" Margin="8" />
</CollectionView.EmptyView>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:LoggedPoint">
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#FAFAFA, Dark=#242426}"
StrokeShape="RoundRectangle 8" Padding="10" Margin="0,2">
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto">
<Label Grid.Row="0" FontSize="13" FontAttributes="Bold">
<Label.Text>
<MultiBinding StringFormat="{}{0} · {1} Hz · depth {2}">
<Binding Path="Utility" Converter="{StaticResource UtilityName}" />
<Binding Path="Frequency" />
<Binding Path="DepthRaw" />
</MultiBinding>
</Label.Text>
</Label>
<Label Grid.Row="0" Grid.Column="1" FontSize="12" TextColor="Gray"
Text="{Binding TimestampUtc, StringFormat='{0:HH:mm:ss}'}" />
<Label Grid.Row="1" Grid.ColumnSpan="2" FontSize="12" TextColor="Gray">
<Label.Text>
<MultiBinding StringFormat="{}{0:F7}, {1:F7} · {2}">
<Binding Path="Latitude" />
<Binding Path="Longitude" />
<Binding Path="FixStatus" Converter="{StaticResource FixStatusName}" />
</MultiBinding>
</Label.Text>
</Label>
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ScrollView>
</ContentPage>