Skip to content

Commit

Permalink
Merge pull request #39 from asv-soft/feat/sdr_calibration
Browse files Browse the repository at this point in the history
Add calibration methods for SDR payload
  • Loading branch information
asvol authored Nov 20, 2023
2 parents 00316bf + 6937fa2 commit 96dc714
Show file tree
Hide file tree
Showing 22 changed files with 2,092 additions and 569 deletions.
4 changes: 2 additions & 2 deletions src/Asv.Mavlink.Shell/Resources/csharp.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,9 @@ namespace Asv.Mavlink.V2.{{ Namespace }}
{%- if field.IsEnum -%}
{%- if field.IsArray -%}
{%- if field.IsTheLargestArrayInMessage -%}
public {{ field.EnumCamelCaseName }}[] {{ field.CamelCaseName }} { get; set; } = new {{ field.Type }}[{{ field.ArrayLength }}];
public {{ field.EnumCamelCaseName }}[] {{ field.CamelCaseName }} { get; set; } = new {{ field.EnumCamelCaseName }}[{{ field.ArrayLength }}];
{%- else -%}
public {{ field.EnumCamelCaseName }}[] {{ field.CamelCaseName }} { get; } = new {{ field.Type }}[{{ field.ArrayLength }}];
public {{ field.EnumCamelCaseName }}[] {{ field.CamelCaseName }} { get; } = new {{ field.EnumCamelCaseName }}[{{ field.ArrayLength }}];
{%- endif -%}
{%- else -%}
public {{ field.EnumCamelCaseName }} {{ field.CamelCaseName }} { get; set; }
Expand Down
198 changes: 186 additions & 12 deletions src/Asv.Mavlink.Test/Microservices/AsvSdr/AsvSdrExTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,34 @@
using Asv.Common;
using Asv.Mavlink.V2.AsvSdr;
using Asv.Mavlink.V2.Common;
using DynamicData;
using DynamicData.Binding;
using Xunit;
using Xunit.Abstractions;

namespace Asv.Mavlink.Test.AsvSdr;
namespace Asv.Mavlink.Test;

public class AsvSdrExTests
{
private readonly ITestOutputHelper _testOutputHelper;

private async Task<(AsvSdrClientEx, AsvSdrServerEx)> SetUpConnection()
private async Task<(IAsvSdrClientEx, IAsvSdrServerEx)> SetUpConnection()
{
var link = new VirtualMavlinkConnection();
var mavlinkClientIdentity = new MavlinkClientIdentity() { SystemId = 1, ComponentId = 1, TargetSystemId = 2, TargetComponentId = 2 };
var heartBeatClient = new HeartbeatClient(link.Client, mavlinkClientIdentity, new PacketSequenceCalculator(), new HeartbeatClientConfig(), Scheduler.Default);
var commandClient = new CommandClient(link.Client, mavlinkClientIdentity, new PacketSequenceCalculator(), new CommandProtocolConfig());
var asvSdrClient = new AsvSdrClient(link.Client, mavlinkClientIdentity, new PacketSequenceCalculator());
var asvSdrClientEx = new AsvSdrClientEx(asvSdrClient, heartBeatClient, commandClient, new AsvSdrClientExConfig());


var pkt = new PacketSequenceCalculator();
var mavlinkServerIdentity = new MavlinkServerIdentity() { SystemId = 2, ComponentId = 2 };
var heartBeatServer = new HeartbeatServer(link.Server, new PacketSequenceCalculator(), mavlinkServerIdentity, new MavlinkHeartbeatServerConfig(), Scheduler.Default);
var commandServer = new CommandServer(link.Server, new PacketSequenceCalculator(), mavlinkServerIdentity, Scheduler.Default);
var heartBeatServer = new HeartbeatServer(link.Server, pkt, mavlinkServerIdentity, new MavlinkHeartbeatServerConfig(), Scheduler.Default);
var commandServer = new CommandServer(link.Server, pkt, mavlinkServerIdentity, Scheduler.Default);
var commandLongServerEx = new CommandLongServerEx(commandServer);
var asvSdrServer = new AsvSdrServer(link.Server, mavlinkServerIdentity, new AsvSdrServerConfig(), new PacketSequenceCalculator(), Scheduler.Default);
var asvSdrServerEx = new AsvSdrServerEx(asvSdrServer, heartBeatServer, commandLongServerEx);
var status = new StatusTextServer(link.Server, pkt, mavlinkServerIdentity, new StatusTextLoggerConfig(), Scheduler.Default);
var asvSdrServer = new AsvSdrServer(link.Server, mavlinkServerIdentity, new AsvSdrServerConfig(), pkt, Scheduler.Default);
var asvSdrServerEx = new AsvSdrServerEx(asvSdrServer,status, heartBeatServer, commandLongServerEx);

heartBeatServer.Start();
asvSdrServer.Start();
Expand All @@ -54,16 +57,17 @@ public async Task Check_For_AsvCustomMode_Set(AsvSdrCustomMode customMode)
{
var (asvSdrClientEx, asvSdrServerEx) = await SetUpConnection();

asvSdrServerEx.SetMode = (mode, hz, rate, ratio, cancel) =>
asvSdrServerEx.SetMode = (mode, hz, rate, ratio, refPower, cancel) =>
{
Assert.Equal(customMode, mode);
Assert.Equal(11223U, hz);
Assert.Equal(1, rate);
Assert.Equal(1U, ratio);
Assert.Equal(-90, refPower);
return Task.FromResult(MavResult.MavResultAccepted);
};

var result = await asvSdrClientEx.SetMode(customMode, 11223, 1, 1, CancellationToken.None);
var result = await asvSdrClientEx.SetMode(customMode, 11223, 1, 1, -90, CancellationToken.None);
Assert.Equal(MavResult.MavResultAccepted, result);
}

Expand All @@ -78,9 +82,9 @@ public async Task Check_For_MavResult_Value(MavResult mavResult)
{
var (asvSdrClientEx, asvSdrServerEx) = await SetUpConnection();

asvSdrServerEx.SetMode = (_, _, _, _, _) => Task.FromResult(mavResult);
asvSdrServerEx.SetMode = (_, _, _, _, _,_) => Task.FromResult(mavResult);

var result = await asvSdrClientEx.SetMode(AsvSdrCustomMode.AsvSdrCustomModeLlz, 11223, 1, 1, CancellationToken.None);
var result = await asvSdrClientEx.SetMode(AsvSdrCustomMode.AsvSdrCustomModeLlz, 11223, 1, 1, -90.5f, CancellationToken.None);
Assert.Equal(mavResult, result);
}

Expand Down Expand Up @@ -769,4 +773,174 @@ public async Task Check_Stop_Mission_Behaviour()
await client.StopMission();

}
}


[Fact]
public async Task Client_call_start_calibration_server_respond()
{
var (client, server) = await SetUpConnection();
server.StartCalibration = (cancel) => Task.FromResult(MavResult.MavResultAccepted);
await client.StartCalibrationAndCheckResult();

}

[Fact]
public async Task Client_call_unsupported_commands()
{
var (client, server) = await SetUpConnection();
await Assert.ThrowsAsync<AsvSdrException>(async () =>
{
await client.StartCalibrationAndCheckResult();
});
await Assert.ThrowsAsync<AsvSdrException>(async () =>
{
await client.StopCalibrationAndCheckResult();
});
}

[Fact]
public async Task Client_read_calibration_table_list()
{
var (client, server) = await SetUpConnection();
var date = DateTime.Now;
server.Base.Set(_ => _.CalibTableCount = 2);
server.ReadCalibrationTableInfo = index =>
{
return index switch
{
0 => new CalibrationTableInfo { Name = "Table 1", Size = 10, Updated = date, },
1 => new CalibrationTableInfo { Name = "Table 2", Size = 20, Updated = date, },
_ => throw new Exception("Invalid table index")
};
};
var status = await client.Base.Status.FirstAsync();
await client.ReadCalibrationTableList();
var sub = client.CalibrationTables.Bind(out var list).Subscribe();
Assert.Equal(2, list.Count);
Assert.Equal("Table 1", list[0].Name);
Assert.Equal("Table 2", list[1].Name);
Assert.Equal(10, list[0].RemoteRowCount.Value);
Assert.Equal(20, list[1].RemoteRowCount.Value);
Assert.Equal(0, list[0].Index);
Assert.Equal(1, list[1].Index);
Assert.True(date - list[0].Updated.Value < TimeSpan.FromMilliseconds(100));
}
[Fact]
public async Task Client_download_calibration_table()
{
var (client, server) = await SetUpConnection();
var date = DateTime.Now;
server.Base.Set(_ => _.CalibTableCount = 2);
server.ReadCalibrationTableInfo = index =>
{
return index switch
{
0 => new CalibrationTableInfo { Name = "Table 1", Size = 10, Updated = date, },
1 => new CalibrationTableInfo { Name = "Table 2", Size = 20, Updated = date, },
_ => throw new Exception("Invalid table index")
};
};
var status = await client.Base.Status.FirstAsync();
await client.ReadCalibrationTableList();
var sub = client.CalibrationTables.Bind(out var list).Subscribe();
Assert.Equal(2, list.Count);
Assert.Equal("Table 1", list[0].Name);
Assert.Equal("Table 2", list[1].Name);
Assert.Equal(10, list[0].RemoteRowCount.Value);
Assert.Equal(20, list[1].RemoteRowCount.Value);
Assert.Equal(0, list[0].Index);
Assert.Equal(1, list[1].Index);
Assert.True(date - list[0].Updated.Value < TimeSpan.FromSeconds(1));
}

[Theory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
public async Task Client_read_calibration_table_rows(ushort count)
{
var (client, server) = await SetUpConnection();
var name = "Table 1";
var date = DateTime.Now;
server.Base.Set(_ => _.CalibTableCount = 1);
server.ReadCalibrationTableInfo = index =>
{
return index switch
{
0 => new CalibrationTableInfo { Name = name, Size = count, Updated = date, },
_ => throw new Exception("Invalid table index")
};
};
server.ReadCalibrationTableRow = (tableIndex, row) =>
{
if (tableIndex != 0) throw new Exception("Invalid table index");
return new CalibrationTableRow(row,row*0.1f,row*20,row*10);
};
var status = await client.Base.Status.FirstAsync();
await client.ReadCalibrationTableList();
var sub = client.CalibrationTables.Bind(out var list).Subscribe();
var table = await client.GetCalibrationTable(name);
Assert.NotNull(table);
Assert.Equal(name, table.Name);
Assert.Equal(count, table.RemoteRowCount.Value);
Assert.Equal(0, table.Index);
Assert.True(date - table.Updated.Value < TimeSpan.FromMilliseconds(100));
var items = await table.Download();
Assert.Equal(count, items.Length);
for (int i = 0; i < count; i++)
{
Assert.Equal((ulong)i, items[i].FrequencyHz);
Assert.Equal(i*0.1f, items[i].RefPower);
Assert.Equal(i*20, items[i].RefValue);
Assert.Equal(i*10, items[i].MeasuredValue);
}
}



[Fact]
public async Task Client_upload_and_download_with_server_error()
{
var (client, server) = await SetUpConnection();
var name = "Table 1";
var date = DateTime.Now;

server.Base.Set(_ => _.CalibTableCount = 1);
server.ReadCalibrationTableInfo = index =>
{
return index switch
{
0 => new CalibrationTableInfo { Name = name, Size = 10, Updated = date, },
_ => throw new Exception("Invalid table index")
};
};
server.WriteCalibrationTable = (tableIndex, items) =>
{
throw new Exception("FATAL");
};
server.ReadCalibrationTableRow = (tableIndex, row) =>
{
throw new Exception("FATAL");
};




var status = await client.Base.Status.FirstAsync();
await client.ReadCalibrationTableList();
var sub = client.CalibrationTables.Bind(out var list).Subscribe();
var table = await client.GetCalibrationTable(name);
Assert.NotNull(table);
await Assert.ThrowsAsync<AsvSdrException>(async () =>
{
var resultEmpty = await table.Download();
});
await Assert.ThrowsAsync<AsvSdrException>(async () =>
{
await table.Upload(new CalibrationTableRow[]{new CalibrationTableRow(100,0,0,0) });
});


}

}
22 changes: 12 additions & 10 deletions src/Asv.Mavlink.Test/Microservices/AsvSdr/AsvSdrHelperTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ public class AsvSdrHelperTest
{

[Theory]
[InlineData(AsvSdrCustomMode.AsvSdrCustomModeLlz, 0, 0, 0)]
[InlineData(AsvSdrCustomMode.AsvSdrCustomModeGp, 330000001, 5, 1)]
public void Check_mission_conversion_for_set_mode(AsvSdrCustomMode mode, ulong frequencyHz, float recordRate, uint sendingThinningRatio)
[InlineData(AsvSdrCustomMode.AsvSdrCustomModeLlz, 0, 0, 0, -10)]
[InlineData(AsvSdrCustomMode.AsvSdrCustomModeGp, 330000001, 5, 1,-60)]
public void Check_mission_conversion_for_set_mode(AsvSdrCustomMode mode, ulong frequencyHz, float recordRate, uint sendingThinningRatio, float refPower)
{
var input = new MissionItemIntPayload();
var buffer = new byte[input.GetByteSize()];
var inputSpan = new Span<byte>(buffer);

AsvSdrHelper.SetArgsForSdrSetMode(input, mode, frequencyHz, recordRate, sendingThinningRatio);
AsvSdrHelper.SetArgsForSdrSetMode(input, mode, frequencyHz, recordRate, sendingThinningRatio,refPower);

input.Serialize(ref inputSpan);

Expand All @@ -27,34 +27,36 @@ public void Check_mission_conversion_for_set_mode(AsvSdrCustomMode mode, ulong f


var serverItem = AsvSdrHelper.Convert(output);
AsvSdrHelper.GetArgsForSdrSetMode(serverItem, out var modeOut, out var frequencyHzOut, out var recordRateOut, out var sendingThinningRatioOut);
AsvSdrHelper.GetArgsForSdrSetMode(serverItem, out var modeOut, out var frequencyHzOut, out var recordRateOut, out var sendingThinningRatioOut, out var outRefPower);
Assert.Equal(mode, modeOut);
Assert.Equal(frequencyHz, frequencyHzOut);
Assert.Equal(recordRate, recordRateOut);
Assert.Equal(sendingThinningRatio, sendingThinningRatioOut);
Assert.Equal(refPower, outRefPower);
}

[Theory]
[InlineData(AsvSdrCustomMode.AsvSdrCustomModeLlz, 0, 0, 0)]
[InlineData(AsvSdrCustomMode.AsvSdrCustomModeGp, 330000001, 5, 1)]
public void Check_command_conversion_for_set_mode(AsvSdrCustomMode mode, ulong frequencyHz, float recordRate, uint sendingThinningRatio)
[InlineData(AsvSdrCustomMode.AsvSdrCustomModeLlz, 0, 0, 0, -10)]
[InlineData(AsvSdrCustomMode.AsvSdrCustomModeGp, 330000001, 5, 1,-60)]
public void Check_command_conversion_for_set_mode(AsvSdrCustomMode mode, ulong frequencyHz, float recordRate, uint sendingThinningRatio, float refPower)
{
var input = new CommandLongPayload();
var buffer = new byte[input.GetByteSize()];
var inputSpan = new Span<byte>(buffer);

AsvSdrHelper.SetArgsForSdrSetMode(input, mode, frequencyHz, recordRate, sendingThinningRatio);
AsvSdrHelper.SetArgsForSdrSetMode(input, mode, frequencyHz, recordRate, sendingThinningRatio, refPower);
input.Serialize(ref inputSpan);

var output = new CommandLongPayload();
var outputSpan = new ReadOnlySpan<byte>(buffer);
output.Deserialize(ref outputSpan);

AsvSdrHelper.GetArgsForSdrSetMode(output, out var modeOut, out var frequencyHzOut, out var recordRateOut, out var sendingThinningRatioOut);
AsvSdrHelper.GetArgsForSdrSetMode(output, out var modeOut, out var frequencyHzOut, out var recordRateOut, out var sendingThinningRatioOut, out var outRefPower);
Assert.Equal(mode, modeOut);
Assert.Equal(frequencyHz, frequencyHzOut);
Assert.Equal(recordRate, recordRateOut);
Assert.Equal(sendingThinningRatio, sendingThinningRatioOut);
Assert.Equal(refPower, outRefPower);
}

[Theory]
Expand Down
Loading

0 comments on commit 96dc714

Please sign in to comment.