JBlam.MavPipe
0.10.3-testing
dotnet add package JBlam.MavPipe --version 0.10.3-testing
NuGet\Install-Package JBlam.MavPipe -Version 0.10.3-testing
<PackageReference Include="JBlam.MavPipe" Version="0.10.3-testing" />
paket add JBlam.MavPipe --version 0.10.3-testing
#r "nuget: JBlam.MavPipe, 0.10.3-testing"
// Install JBlam.MavPipe as a Cake Addin #addin nuget:?package=JBlam.MavPipe&version=0.10.3-testing&prerelease // Install JBlam.MavPipe as a Cake Tool #tool nuget:?package=JBlam.MavPipe&version=0.10.3-testing&prerelease
JBlam.MavPipe
This is the "protocol-level" component of MavPipe. If you want to use a well-known Mavlink dialect (like common.xml
or ardupilotmega.xml
), don't use this package directly; instead, reference the type library (for example JBlam.MavPipe.Common
or JBlam.MavPipe.ArduPilotMega
).
TODO: release those packages
Getting started
See the project documentation for a quick intro example.
Getting messages
Assuming you have a MavPipeReader
, you can get access to strongly-typed messages as an observable.
using JBlam.MavPipe;
static void GetMessages(MavPipeReader reader, IObserver<Heartbeat> observer)
{
// Subscribe to messages from the autopilot (system ID 1, component ID 1)
IObservable<Heartbeat> heartbeats = reader.GetMessages<Heartbeat>(new SystemComponent(1, 1));
// observer's OnNext method will be invoked every time a heartbeat is parsed.
// Consider using System.Reactive instead of implementing IObserver yourself.
IDisposable subscription = heartbeats.Subscribe(observer);
// Disposing the subscription stops observing heartbeats, but does not stop
// the reader from parsing the input.
subscription.Dispose();
}
The observables are hot; that is, subscribing or unsubscribing does not control the reader. The reader is controlled by calling Task MavPipeReader.Read(PipeReader, IObserver<ParseEvent>?, CancellationToken)
.
If you want to observe a diverse set of messages in sequence, you'll need to do some advance RxNet queries. See Intro To RX to find out more about dealing with IObservable<T>
.
If you want to observe every kind of message in a uniform format, consider the JSON or Passthrough features below.
Passthrough
If you have a MavPipeReader, you may want to also access the source bytes. For example:
- If you are making some kind of router which must parse messages and send them on to another recipient.
- If you want to log the data sent and recieved for later analysis.
The Passthrough
property of MavPipeReader provides access to the source data, with the ability to perform some filtering. It can also produce a TLOG formatted data stream.
To my knowledge TLOG is not formally defined. The informal definition, based on my reverse-engineering of Mission Planner's output, is that every valid Mavlink packet is prepended with a 64-bit big-endian timestamp of milliseconds since Unix epoch.
using JBlam.MavPipe;
using JBlam.MavPipe.Observability;
using System.IO.Pipelines;
static void ObservePassthrough(MavPipeReader reader)
{
// We can get all the bytes, regardless of whether the data is valid.
PipeReader everything = reader.Passthrough.Subscribe();
// We can get only valid packets
PipeReader valid = reader.Passthrough.SubscribeValidPackets();
// We can also get TLOGs
PipeReader tlogs = reader.Passthrough.SubscribeTLogs();
}
Parse events
The parse communicates validity of the input stream using the IObserver<ParseEvent>
parameter of MavPipeReader.Read(PipeReader, IObserver<ParseEvent>, CancellationToken)
.
ParseEvent
structs are generated for each attempt to read a packet from the input. The reader guarantees that every byte read from the input is represented by exactly one ParseEvent
: that is, summing the values of ParseEvent.ConsumedByteCount
over every ParseEvent
will give the exact length of the input stream.
The ParseEvent.Header
property is generated for valid and invalid packets alike. It is not possible for MavPipe to know the difference between a message type that it doesn't understand, versus completely random garbage. If the ParseEvent.Outcome
value does not indicate a successfully-parsed packet, treat the header data with skepticism.
JSON
You may want to observe Mavlink packets in a uniform, more flexible, or simple-to-consume format. For example, if you want to present the latest value of every message type in a user interface. Subscribing an observable for every single kind of message would not be maintainable.
MavPipeReader provides a JSON observable as a convenient API for diong this.
using JBlam.MavPipe;
static void GetMessagesAsJson(MavPipeReader reader, IObserver<MessageJson> observer)
{
// The semantics of the JSON observable are the same as for the strongly-typed
// GetMessages<T>() observables.
IDisposable subscription = reader.GetMessagesAsJson().Subscribe(observer);
// MessageJson is a MavPipe struct which provides the message content as JSON,
// but the header is a .NET struct.
}
Reparsing every message as JSON incurs a noticeable performance cost. It is recommended to use GetMessages<T>()
if you want to work with any number of specific message types.
If you need to work with non-standard message types (that is, not one of the "dialects" specified by the Mavlink project, such as common) consider using the Generator to create a type library.
Use a custom type library
If you're creating your own custom type library, use the JBlam.MavPipe.Generator
tool to generate C# source.
TODO: more detailed docs on how to do that.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. 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 is compatible. 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. |
-
net6.0
- Microsoft.Bcl.TimeProvider (>= 8.0.1)
- System.IO.Pipelines (>= 6.0.3)
- System.Reactive (>= 6.0.0)
-
net7.0
- Microsoft.Bcl.TimeProvider (>= 8.0.1)
- System.IO.Pipelines (>= 6.0.3)
- System.Reactive (>= 6.0.0)
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 |
---|---|---|
0.10.3-testing | 38 | 11/1/2024 |
0.10.2-testing | 75 | 8/16/2024 |
0.10.1-testing | 53 | 6/4/2024 |
0.10.0-testing | 51 | 6/4/2024 |
0.9.0-testing | 55 | 6/3/2024 |