Setup task completion source and cancellation token
Create a task completion source. You'll need it to wait for a response from the server.
var tcs = new TaskCompletionSource<HeartbeatPayload>();
Create a cancellation token source with a timeout. The cancellation token will trigger after 20 seconds. You can change this by setting a different time span.
using var cancel = new CancellationTokenSource(TimeSpan.FromSeconds(20), TimeProvider.System);
Register a delegate that will be called when the cancellation token is canceled. This will stop tcs from running in a loop when the token fails.
using Asv.Cfg;
using Asv.IO;
using Asv.Mavlink;
using ObservableCollections;
using R3;
// Setup
var tcs = new TaskCompletionSource();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20), TimeProvider.System);
await using var s = cts.Token.Register(() => tcs.TrySetCanceled());
//
// Router creation
var protocol = Protocol.Create(builder =>
{
builder.RegisterMavlinkV2Protocol();
builder.Features.RegisterBroadcastFeature<MavlinkMessage>();
builder.Formatters.RegisterSimpleFormatter();
});
await using var router = protocol.CreateRouter("ROUTER");
router.AddTcpClientPort(p =>
{
p.Host = "127.0.0.1";
p.Port = 5760;
});
//
// Device explorer creation
var seq = new PacketSequenceCalculator();
var identity = new MavlinkIdentity(255, 255);
await using var deviceExplorer = DeviceExplorer.Create(router, builder =>
{
builder.SetConfig(new ClientDeviceBrowserConfig()
{
DeviceTimeoutMs = 1000,
DeviceCheckIntervalMs = 30_000,
});
builder.Factories.RegisterDefaultDevices(
new MavlinkIdentity(identity.SystemId, identity.ComponentId),
seq,
new InMemoryConfiguration());
});
//
// Device search
IClientDevice? drone = null;
using var sub = deviceExplorer.Devices
.ObserveAdd()
.Take(1)
.Subscribe(kvp =>
{
drone = kvp.Value.Value;
tcs.TrySetResult();
});
await tcs.Task;
if (drone is null)
{
throw new Exception("Drone not found");
}
//
// Drone init
tcs = new TaskCompletionSource();
using var sub2 = drone.State
.Subscribe(x =>
{
if (x != ClientDeviceState.Complete)
{
return;
}
tcs.TrySetResult();
});
await tcs.Task;
//
// Heartbeat client search
await using var heartbeat = drone?.GetMicroservice<IHeartbeatClient>();
if (heartbeat is null)
{
throw new Exception("No control client found");
}
//
// Test
tcs = new TaskCompletionSource();
var count = 0;
using var sub3 = heartbeat.RawHeartbeat
.ThrottleLast(TimeSpan.FromMilliseconds(100))
.Subscribe(p =>
{
if (p is null)
{
return;
}
Console.WriteLine($"Heartbeat type: {p.Type}, Heartbeat baseMode: {p.BaseMode}");
if (count >= 19)
{
tcs.TrySetResult();
return;
}
count++;
});
await tcs.Task;
//