Skip to content

Commit ec95cc7

Browse files
committed
Added response parser for read commands
1 parent 075d3bd commit ec95cc7

7 files changed

Lines changed: 218 additions & 2 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System.Collections.Generic;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using TelloCommander.Response;
4+
5+
namespace TelloCommander.Tests
6+
{
7+
[TestClass]
8+
public class ResponseParserTest
9+
{
10+
[TestMethod]
11+
public void ParseToNumberTest()
12+
{
13+
decimal result = ResponseParser.ParseToNumber("6dm");
14+
Assert.AreEqual(6, result);
15+
}
16+
17+
[TestMethod]
18+
public void ParseToRangeTest()
19+
{
20+
(decimal minimum, decimal maximum) range = ResponseParser.ParseToRange("60~61C");
21+
Assert.AreEqual(60, range.minimum);
22+
Assert.AreEqual(61, range.maximum);
23+
}
24+
25+
[TestMethod]
26+
public void ParseToDictionaryTest()
27+
{
28+
Dictionary<string, string> dictionary = ResponseParser.ParseToDictionary("pitch:9;roll:-36;yaw:-51;");
29+
Assert.AreEqual("9", dictionary["pitch"]);
30+
Assert.AreEqual("-36", dictionary["roll"]);
31+
Assert.AreEqual("-51", dictionary["yaw"]);
32+
}
33+
34+
[TestMethod]
35+
public void ParseToAccelerationTest()
36+
{
37+
Acceleration acceleration = ResponseParser.ParseToAcceleration("agx:-65.00;agy:31.00;agz:-994.00;");
38+
Assert.AreEqual(-65, acceleration.X);
39+
Assert.AreEqual(31, acceleration.Y);
40+
Assert.AreEqual(-994, acceleration.Z);
41+
}
42+
43+
[TestMethod]
44+
public void ParseToAttitudeTest()
45+
{
46+
Attitude attitude = ResponseParser.ParseToAttitude("pitch:9;roll:-36;yaw:-51;");
47+
Assert.AreEqual(9, attitude.Pitch);
48+
Assert.AreEqual(-36, attitude.Roll);
49+
Assert.AreEqual(-51, attitude.Yaw);
50+
}
51+
52+
[TestMethod]
53+
public void ParseToTemperatureTest()
54+
{
55+
Temperature temperature = ResponseParser.ParseToTemperature("60~61C");
56+
Assert.AreEqual(60, temperature.Minimum);
57+
Assert.AreEqual(61, temperature.Maximum);
58+
}
59+
}
60+
}

src/TelloCommander.Tests/TelloCommander.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>netcoreapp3.0</TargetFramework>
55

66
<IsPackable>false</IsPackable>
7-
<ReleaseVersion>1.0.0</ReleaseVersion>
7+
<ReleaseVersion>1.0.0.2</ReleaseVersion>
88
</PropertyGroup>
99

1010
<ItemGroup>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace TelloCommander.Response
2+
{
3+
public class Acceleration
4+
{
5+
public decimal X { get; set; }
6+
public decimal Y { get; set; }
7+
public decimal Z { get; set; }
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace TelloCommander.Response
2+
{
3+
public class Attitude
4+
{
5+
public decimal Pitch { get; set; }
6+
public decimal Roll { get; set; }
7+
public decimal Yaw { get; set; }
8+
}
9+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace TelloCommander.Response
6+
{
7+
public static class ResponseParser
8+
{
9+
private static readonly char[] _numeric = { '-', '.' };
10+
11+
/// <summary>
12+
/// Parse a value string to a number, returning null if there's a conversion error
13+
/// </summary>
14+
/// <param name="valueString"></param>
15+
/// <returns></returns>
16+
public static decimal ParseToNumber(string valueString)
17+
{
18+
string numericString = new string(valueString.Where(c => char.IsDigit(c) || (_numeric.Contains(c))).ToArray());
19+
decimal value = decimal.Parse(numericString);
20+
return value;
21+
}
22+
23+
/// <summary>
24+
/// Parse a range response into a tuple of numbers
25+
/// </summary>
26+
/// <param name="response"></param>
27+
/// <returns></returns>
28+
public static (decimal minimum, decimal maximum) ParseToRange(string response)
29+
{
30+
// A typical range might look like this:
31+
//
32+
// 65~66C
33+
string[] words = response.Trim().Split(new char[] { '~' }, StringSplitOptions.None);
34+
decimal minimum = ParseToNumber(words[0]);
35+
decimal maximum = ParseToNumber(words[1]);
36+
37+
return (minimum, maximum);
38+
}
39+
40+
/// <summary>
41+
/// Parse a multi-property response into a dictionary of properties
42+
/// </summary>
43+
/// <param name="response"></param>
44+
/// <returns></returns>
45+
public static Dictionary<string, string> ParseToDictionary(string response)
46+
{
47+
Dictionary<string, string> values = new Dictionary<string, string>();
48+
49+
// A typical response might look like this, with the property name and value
50+
// in pairs separated by ":" and each property separated from the last by ";"
51+
//
52+
// agx:118.00;agy:-54.00;agz:-991.00;
53+
54+
// If the response ends with the key-value pair ";" separator, we need to
55+
// remove it so we don't end up with a spurious empty entry when we split
56+
// the string. We can't use the string split option to remove empty entries
57+
// as there may be legitimate blank values in the response
58+
if (response.EndsWith(";", StringComparison.CurrentCulture))
59+
{
60+
response = response.Substring(0, response.Length - 1);
61+
}
62+
63+
// Split the response on the value and pair separators
64+
string[] words = response.Trim().Split(new char[] { ':', ';' }, StringSplitOptions.None);
65+
for (int i = 0; i <= words.Length - 2; i += 2)
66+
{
67+
values.Add(words[i], words[i + 1]);
68+
}
69+
70+
return values;
71+
}
72+
73+
/// <summary>
74+
/// Parse a response into an acceleration
75+
/// </summary>
76+
/// <param name="response"></param>
77+
/// <returns></returns>
78+
public static Acceleration ParseToAcceleration(string response)
79+
{
80+
Dictionary<string, string> properties = ParseToDictionary(response);
81+
82+
Acceleration acceleration = new Acceleration
83+
{
84+
X = ParseToNumber(properties["agx"]),
85+
Y = ParseToNumber(properties["agy"]),
86+
Z = ParseToNumber(properties["agz"])
87+
};
88+
89+
return acceleration;
90+
}
91+
92+
/// <summary>
93+
/// Parse a response into an attitude
94+
/// </summary>
95+
/// <param name="response"></param>
96+
/// <returns></returns>
97+
public static Attitude ParseToAttitude(string response)
98+
{
99+
Dictionary<string, string> properties = ParseToDictionary(response);
100+
101+
Attitude attitude = new Attitude
102+
{
103+
Pitch = ParseToNumber(properties["pitch"]),
104+
Roll = ParseToNumber(properties["roll"]),
105+
Yaw = ParseToNumber(properties["yaw"])
106+
};
107+
108+
return attitude;
109+
}
110+
111+
/// <summary>
112+
/// Parse a response into a temperature range
113+
/// </summary>
114+
/// <param name="response"></param>
115+
/// <returns></returns>
116+
public static Temperature ParseToTemperature(string response)
117+
{
118+
(decimal minimum, decimal maximum) tuple = ParseToRange(response);
119+
120+
Temperature temperature = new Temperature
121+
{
122+
Minimum = tuple.minimum,
123+
Maximum = tuple.maximum
124+
};
125+
126+
return temperature;
127+
}
128+
}
129+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace TelloCommander.Response
2+
{
3+
public class Temperature
4+
{
5+
public decimal Minimum { get; set; }
6+
public decimal Maximum { get; set; }
7+
}
8+
}

src/TelloCommander/TelloCommander.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<TargetFramework>netstandard2.1</TargetFramework>
55
<PackageId>TelloCommander</PackageId>
6-
<ReleaseVersion>1.0.0</ReleaseVersion>
6+
<ReleaseVersion>1.0.0.2</ReleaseVersion>
77
<PackageVersion>1.0.0.1</PackageVersion>
88
<Authors>Dave Walker</Authors>
99
<Copyright>Copyright (c) 2020 Dave Walker</Copyright>
@@ -21,6 +21,7 @@
2121
<Folder Include="Simulator\" />
2222
<Folder Include="CommandDictionaries\" />
2323
<Folder Include="Content\" />
24+
<Folder Include="Response\" />
2425
</ItemGroup>
2526
<ItemGroup>
2627
<None Remove="Content\CommandDictionary-1.3.0.0.xml" />

0 commit comments

Comments
 (0)