FlySight 1.0.0
dotnet add package FlySight --version 1.0.0
NuGet\Install-Package FlySight -Version 1.0.0
<PackageReference Include="FlySight" Version="1.0.0" />
<PackageVersion Include="FlySight" Version="1.0.0" />
<PackageReference Include="FlySight" />
paket add FlySight --version 1.0.0
#r "nuget: FlySight, 1.0.0"
#:package FlySight@1.0.0
#addin nuget:?package=FlySight&version=1.0.0
#tool nuget:?package=FlySight&version=1.0.0
FlySight.NET
FlySight.NET is a small, focused .NET library for parsing FlySight CSV logs (including FlySight 2). It provides memory-efficient streaming readers (sync + async), a lightweight sample model, and LINQ-style helpers for filtering and summarizing data.
This README documents what the library does, its design principles, and practical examples to get you productive quickly.
Key features
- Streaming parsing from any TextReader (works with files, network streams, pipes).
- Synchronous and asynchronous APIs: read line-by-line without loading entire files into memory.
- Robust handling of headers, missing/extra columns, comments, and blank lines.
- Preserves unknown/extra columns via
RawandExtramaps on each sample. - Small, dependency-free API surface targeting .NET Standard 2.1.
Installation
- Target framework:
netstandard2.1(works from .NET Core/.NET 5+/Mono that supports netstandard2.1). - Add a project reference to the
FlySightproject, or build and reference the assembly. If packaged, install via NuGet when available.
Example (add project reference inside solution):
# from repository root
dotnet add tests/FlySight.Tests/FlySight.Tests.csproj reference src/FlySight/FlySight.csproj
Quick start
Below are minimal examples showing common usage patterns. Replace path/to/log.csv with your file path.
Synchronous file streaming
using FlySight;
foreach (var sample in FlySightReader.ReadFile("path/to/log.csv"))
{
Console.WriteLine($"{sample.Time:u} lat={sample.Latitude:F6} lon={sample.Longitude:F6} 3d={sample.Speed3D:F2} m/s");
}
Asynchronous streaming (useful for large files or UI apps)
using FlySight;
await foreach (var sample in FlySightReader.ReadFileAsync("path/to/log.csv"))
{
// process sample
}
Parsing from an arbitrary TextReader / stream
Use Read and ReadAsync when you already have a TextReader (e.g., a StreamReader over a network stream or a compressed input).
using var stream = File.OpenRead("path/to/log.csv");
using var reader = new StreamReader(stream);
foreach (var sample in FlySightReader.Read(reader))
{
// ...
}
// async variant
using var stream2 = File.OpenRead("path/to/log.csv");
using var reader2 = new StreamReader(stream2);
await foreach (var sample in FlySightReader.ReadAsync(reader2))
{
// ...
}
API reference (essential surface)
FlySightReader
- IEnumerable<FlySightSample> Read(TextReader reader, CancellationToken cancellationToken = default)
- IAsyncEnumerable<FlySightSample> ReadAsync(TextReader reader, CancellationToken cancellationToken = default)
- IEnumerable<FlySightSample> ReadFile(string path, CancellationToken cancellationToken = default)
- IAsyncEnumerable<FlySightSample> ReadFileAsync(string path, CancellationToken cancellationToken = default)
FlySightSample (model)
- DateTimeOffset Time
- double Latitude
- double Longitude
- double HeightMSL
- double VelocityNorth
- double VelocityEast
- double VelocityDown
- double? HorizontalAccuracy
- double? VerticalAccuracy
- double? SpeedAccuracy
- int? GpsFix
- int? Satellites
- IReadOnlyDictionary<string,string> Raw — all raw fields by name (header names preserved)
- IReadOnlyDictionary<string,string> Extra — unknown/right-hand fields preserved
- double Speed3D — computed 3D speed
QueryExtensions (LINQ helpers)
- Between(startInclusive, endExclusive)
- WhereFixAtLeast(minFix) / WhereFix3D()
- WithAccuracy(maxHorizontalMeters, maxVerticalMeters)
- WithinBounds(minLat, maxLat, minLon, maxLon)
- Summary() — returns (start, end, count)? or null when empty
File format and parsing rules
Supported input: standard FlySight CSV logs. The library accepts logs with or without a header row.
If the first non-empty, non-comment line looks like a header (the parser checks for known column names like
time,lat,lonin the first few fields), that header is used to name fields inRaw/Extramaps. Otherwise, a default column order is assumed:time, lat, lon, hMSL, velN, velE, velD, hAcc, vAcc, sAcc, gpsFix, numSV
Blank lines and lines starting with
#are ignored.If required fields are missing on a data row (time, lat, lon, hMSL, velN, velE, velD), the row is skipped.
Time strings are parsed as ISO8601 with normalization to UTC. Fractional-second formats are supported.
Extra columns to the right are kept and accessible through
FlySightSample.ExtraandFlySightSample.Raw.
Error handling and resilience
- Parsing is defensive: malformed rows are ignored rather than raising exceptions — this is intentional for streaming robustness.
- Callers who need strict validation should post-filter and validate
FlySightSample.Rawvalues or wrap parsing calls and detect when expected rows are missing. - Cancellation tokens are honored by the
ReadFileandReadFileAsyncAPIs where provided.
Performance notes
- The parser is intentionally streaming and avoids buffering whole files in memory. Use the async readers for large files or IO-bound scenarios.
- For very large workloads, prefer
ReadAsyncwithawait foreachto avoid blocking threadpool threads. - Buffer sizes and encoding detection mimic standard
StreamReaderdefaults and can be adjusted by creating your ownStreamReaderand callingRead/ReadAsyncdirectly.
Testing
- Unit tests live under
tests/FlySight.Tests. Run them with:
dotnet test "c:\Repos\FlySight.NET\FlySight.NET.sln"
- The test suite includes parsing, async streaming, malformed lines handling, and large-file streaming tests.
Examples and common patterns
- Filtering GPS-quality points and summarizing:
var good = FlySightReader.ReadFile("log.csv")
.WhereFix3D()
.WithAccuracy(maxHorizontalMeters: 5.0, maxVerticalMeters: 5.0)
.Between(DateTimeOffset.Parse("2025-01-01T00:00:00Z"), DateTimeOffset.Parse("2025-01-02T00:00:00Z"))
.ToList();
var summary = good.Summary();
- Accessing extra fields (header present):
var sample = FlySightReader.ReadFile("log.csv").First();
if (sample.Raw.TryGetValue("note", out var note)) Console.WriteLine(note);
foreach (var kv in sample.Extra) Console.WriteLine($"{kv.Key} = {kv.Value}");
Contributing
- The repository is organized with the
src/FlySightproject andtests/FlySight.Tests. - Please open issues for bugs or feature requests. For code changes, fork, create a feature branch, add tests for new behavior, and open a pull request.
Guidelines
- Keep public API surface small and stable.
- Add tests for parsing edge cases and streaming behavior.
- Keep performance characteristics in mind (streaming vs in-memory).
Troubleshooting
- If you see zero samples parsed, confirm the file encoding and that the first non-comment line is a header or valid data row.
- If using the library in a non-UTF8 environment, create the
StreamReaderyourself with the correct encoding and callRead/ReadAsync. - To debug parsing, inspect
FlySightSample.Rawto see exactly what column values were read.
License
This project follows the license present in the repository (add or update the LICENSE file as needed).
Contact / Maintainers
- See
AGENTS.mdor the repository maintainers list for contact and contribution routing.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 179 | 9/9/2025 |