Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void Create_WithLength16DeviceData_UsesCorrectDeviceIdAndSequence()
result.Should().NotBeNull()
.And.BeOfType<RaceCarMessageEncoderRev2>();

var encoded = result!.Encode([Half.Zero, Half.Zero, Half.Zero], true);
var encoded = result!.Encode([Half.Zero, Half.Zero, Half.Zero, Half.Zero], true);
encoded.Length.Should().Be(16);
// Verify deviceId is present in output (bytes 3-4)
encoded[3].Should().Be(0xC9);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ namespace BrickController2.Tests.DeviceManagement.CaDA;
public class RaceCarMessageEncoderRev2Tests
{
[Theory]
[InlineData(0xB920, 0x4076, 0x32, 0x32, 0xB2)] //AA111120B97640 323200B2A1 CCB892A0
[InlineData(0xb920, 0x4076, 0x32, 0x32, 0xb2)] // aa 11 11 20 b9 76 40 32 32 00 b2 a1 cc b8 92 a0
public void EncodeValues_Connect_ReturnsProperPayload(ushort deviceId, ushort appId,
byte v1, byte v2, byte v4)
{
// arrange
var encoder = Create(deviceId, appId);

// act
var result = encoder.EncodeValues([Zero, Zero, Zero], true);
var result = encoder.EncodeValues([Zero, Zero, Zero, Zero], true);

// assert
result.Length.Should().Be(16);
Expand All @@ -27,24 +27,24 @@ public void EncodeValues_Connect_ReturnsProperPayload(ushort deviceId, ushort ap
0xAA, 0x11, 0x11,
(byte)(deviceId & 0xFF), (byte)((deviceId >> 8) & 0xFF),
(byte)(appId & 0xFF), (byte)((appId >> 8) & 0xFF),
v1, v2, 0x00, v4,
v1, v2, 0b00, v4,
0xA1, 0xCC, 0xB8, 0x92, 0xA0
]);
}

[Theory]
[InlineData(0xB920, 0x42AD, 0x8C, 0x8C, 0x0C)] //BB111120B9AD42 8C8C000C A1CCB892B0
[InlineData(0xB920, 0x5188, 0x76, 0x76, 0xF6)] //BB111120B98851 767600F6 A1CCB892B0
[InlineData(0xB920, 0x4076, 0x53, 0x53, 0xD3)] //BB111120B97640 535300D3 A1CCB892B0
[InlineData(0xC1C9, 0xA4B7, 0xa9, 0xa9, 0x29)] // bb 11 11 c9 c1 b7 a4 a9 a9 00 29 a1 cc b8 92 b0
[InlineData(0xb920, 0x42ad, 0x8c, 0x8c, 0x0c)] // bb 11 11 20 b9 ad 42 8c 8c 00 0c a1 cc b8 92 b0
[InlineData(0xb920, 0x5188, 0x76, 0x76, 0xf6)] // bb 11 11 20 b9 88 51 76 76 00 f6 a1 cc b8 92 b0
[InlineData(0xb920, 0x4076, 0x53, 0x53, 0xd3)] // bb 11 11 20 b9 76 40 53 53 00 d3 a1 cc b8 92 b0
[InlineData(0xc1c9, 0xa4b7, 0xa9, 0xa9, 0x29)] // bb 11 11 c9 c1 b7 a4 a9 a9 00 29 a1 cc b8 92 b0
public void EncodeValues_WithZeroValues_ReturnsProperPayload(ushort deviceId, ushort appId,
byte v1, byte v2, byte v4)
{
// arrange
var encoder = Create(deviceId, appId);

// act
var result = encoder.EncodeValues([Zero, Zero, Zero], false);
var result = encoder.EncodeValues([Zero, Zero, Zero, Zero], false);

// assert
result.Length.Should().Be(16);
Expand All @@ -53,22 +53,22 @@ public void EncodeValues_WithZeroValues_ReturnsProperPayload(ushort deviceId, us
0xBB, 0x11, 0x11,
(byte)(deviceId & 0xFF), (byte)((deviceId >> 8) & 0xFF),
(byte)(appId & 0xFF), (byte)((appId >> 8) & 0xFF),
v1, v2, 0x00, v4,
v1, v2, 0b00, v4,
0xA1, 0xCC, 0xB8, 0x92, 0xB0
]);
}

[Theory]
[InlineData(0xB920, 0x4076, 0x54, 0x54, 0xD4)] //BB111120B97640 545401D4A1 CCB892B0
[InlineData(0xC1C9, 0xA4B7, 0xaa, 0xaa, 0x2a)] // bb 11 11 c9 c1 b7 a4 aa aa 01 2a a1 cc b8 92 b0
public void EncodeValues_WithZeroValuesAndLightOn_ReturnsProperPayload(ushort deviceId, ushort appId,
[InlineData(0xb920, 0x4076, 0x56, 0x56, 0xd6)] // bb 11 11 20 b9 76 40 56 56 03 d6 a1 cc b8 92 b0
[InlineData(0xc1c9, 0xa4b7, 0xac, 0xac, 0x2c)] // bb 11 11 c9 c1 b7 a4 ac ac 03 2c a1 cc b8 92 b0
public void EncodeValues_WithZeroValuesAndFrontLightOnAndRearLightOn_ReturnsProperPayload(ushort deviceId, ushort appId,
byte v1, byte v2, byte v4)
{
// arrange
var encoder = Create(deviceId, appId);

// act
var result = encoder.EncodeValues([Zero, Zero, One]);
var result = encoder.EncodeValues([Zero, Zero, One, One]);

// assert
result.Length.Should().Be(16);
Expand All @@ -77,27 +77,27 @@ public void EncodeValues_WithZeroValuesAndLightOn_ReturnsProperPayload(ushort de
0xBB, 0x11, 0x11,
(byte)(deviceId & 0xFF), (byte)((deviceId >> 8) & 0xFF),
(byte)(appId & 0xFF), (byte)((appId >> 8) & 0xFF),
v1, v2, 0x01, v4,
v1, v2, 0b11, v4,
0xA1, 0xCC, 0xB8, 0x92, 0xB0
]);
}

[Theory]
[InlineData(0xB920, 0x4076, -1.00f, 0x3E, 0xBE, 0xBE, 0x0B)] //BB111120B97640 3EBE01BE0B CCB892B0
[InlineData(0xB920, 0x4076, -0.75f, 0xFE, 0x5E, 0x7E, 0xAB)] //BB111120B97640 FE5E017EAB CCB892B0
[InlineData(0xC1C9, 0xA4B7, -0.75f, 0x4a, 0xea, 0xca, 0xa1)] //bb 11 11 c9 c1 b7 a4 4a ea 01 ca a1 cc b8 92 b0
[InlineData(0xC1C9, 0x2979, -0.75f, 0x9b, 0x3b, 0x1b, 0xab)] //bb 11 11 c9 c1 79 29 9b 3b 01 1b ab cc b8 92 b0
[InlineData(0xB920, 0x4076, 1.000f, 0xAA, 0xD5, 0x2A, 0x78)] //BB111120B97640 AAD5BE0178 CCB892B0
[InlineData(0xC1C9, 0xA4B7, 0.746f, 0x9d, 0xc2, 0x1d, 0x35)] // bb 11 11 c9 c1 b7 a4 9d c2 01 1d 35 cc b8 92 b0
[InlineData(0xC1C9, 0x2979, 0.746f, 0x1b, 0x44, 0x9b, 0x6c)] // bb 11 11 c9 c1 79 29 1b 44 01 9b 6c cc b8 92 b0
public void EncodeValues_WithPartialSteeringAndLightOn_ReturnsProperPayload(ushort deviceId, ushort appId,
[InlineData(0xb920, 0x4076, -1.00f, 0x40, 0xc0, 0xc0, 0x0b)] // bb 11 11 20 b9 76 40 40 c0 03 c0 0b cc b8 92 b0
[InlineData(0xb920, 0x4076, -0.75f, 0x00, 0xa0, 0x80, 0xab)] // bb 11 11 20 b9 76 40 00 a0 03 80 ab cc b8 92 b0
[InlineData(0xc1c9, 0xa4b7, -0.75f, 0x4c, 0xec, 0xcc, 0xa1)] // bb 11 11 c9 c1 b7 a4 4c ec 03 cc a1 cc b8 92 b0
[InlineData(0xc1c9, 0x2979, -0.75f, 0x9d, 0x3d, 0x1d, 0xab)] // bb 11 11 c9 c1 79 29 9d 3d 03 1d ab cc b8 92 b0
[InlineData(0xb920, 0x4076, 1.000f, 0xac, 0xd3, 0x2c, 0x78)] // bb 11 11 20 b9 76 40 aa ac d3 03 2c cc b8 92 b0
[InlineData(0xc1c9, 0xa4b7, 0.746f, 0x9f, 0xc0, 0x1f, 0x35)] // bb 11 11 c9 c1 b7 a4 9f c0 03 1f 35 cc b8 92 b0
[InlineData(0xc1c9, 0x2979, 0.746f, 0x1d, 0x42, 0x9d, 0x6c)] // bb 11 11 c9 c1 79 29 1d 42 03 9d 6c cc b8 92 b0
public void EncodeValues_WithPartialSteeringAndFrontLightOnAndRearLightOn_ReturnsProperPayload(ushort deviceId, ushort appId,
float value, byte v1, byte v2, byte v4, byte sequence)
{
// arrange
var encoder = Create(deviceId, appId, sequence: (byte)(sequence - 1));

// act
var result = encoder.EncodeValues([Zero, (Half)value, One]);
var result = encoder.EncodeValues([Zero, (Half)value, One, One]);

// assert
result.Length.Should().Be(16);
Expand All @@ -106,21 +106,21 @@ public void EncodeValues_WithPartialSteeringAndLightOn_ReturnsProperPayload(usho
0xBB, 0x11, 0x11,
(byte)(deviceId & 0xFF), (byte)((deviceId >> 8) & 0xFF),
(byte)(appId & 0xFF), (byte)((appId >> 8) & 0xFF),
v1, v2, 0x01, v4,
v1, v2, 0b11, v4,
sequence, 0xCC, 0xB8, 0x92, 0xB0
]);
}

[Theory]
[InlineData(0xC1C9, 0x2979, 1.000f, 0x4A, 0xCA, 0x4A, 0xFA)] // bb 11 11 c9 c1 79 29 4a ca 01 4a fa cc b8 92 b0
public void EncodeValues_WithPartialSpeedAndLightOn_ReturnsProperPayload(ushort deviceId, ushort appId,
[InlineData(0xC1C9, 0x2979, 1.000f, 0x4C, 0xCC, 0x4C, 0xFA)] // bb 11 11 c9 c1 79 29 4a ca 01 4a fa cc b8 92 b0
public void EncodeValues_WithPartialSpeedAndFrontLightOnAndRearLightOn_ReturnsProperPayload(ushort deviceId, ushort appId,
float value, byte v1, byte v2, byte v4, byte sequence)
{
// arrange
var encoder = Create(deviceId, appId, sequence: (byte)(sequence - 1));

// act
var result = encoder.EncodeValues([(Half)value, Zero, One]);
var result = encoder.EncodeValues([(Half)value, Zero, One, One]);

// assert
result.Length.Should().Be(16);
Expand All @@ -129,7 +129,7 @@ public void EncodeValues_WithPartialSpeedAndLightOn_ReturnsProperPayload(ushort
0xBB, 0x11, 0x11,
(byte)(deviceId & 0xFF), (byte)((deviceId >> 8) & 0xFF),
(byte)(appId & 0xFF), (byte)((appId >> 8) & 0xFF),
v1, v2, 0x01, v4,
v1, v2, 0b11, v4,
sequence, 0xCC, 0xB8, 0x92, 0xB0
]);
}
Expand All @@ -143,7 +143,7 @@ public void EncodeValues_WithMiddleFirstChannel_ReturnsProperPayload(ushort devi
var encoder = Create(deviceId, appId, sequence: (byte)(sequence - 1));

// act
var result = encoder.EncodeValues([(Half)value, Zero, Zero]);
var result = encoder.EncodeValues([(Half)value, Zero, Zero, Zero]);

// assert
result.Length.Should().Be(16);
Expand All @@ -152,7 +152,53 @@ public void EncodeValues_WithMiddleFirstChannel_ReturnsProperPayload(ushort devi
0xBB, 0x11, 0x11,
(byte)(deviceId & 0xFF), (byte)((deviceId >> 8) & 0xFF),
(byte)(appId & 0xFF), (byte)((appId >> 8) & 0xFF),
v1, v2, 0x00, v4,
v1, v2, 0b00, v4,
sequence, 0xCC, 0xB8, 0x92, 0xB0
]);
}

[Theory]
[InlineData(0xC1C9, 0x2979, 0x4A, 0x4A, 0xCA, 0xFA)] // bb 11 11 c9 c1 79 29 4a 4a 01 ca fa cc b8 92 b0
public void EncodeValues_WithZeroValuesAndFrontLightOnAndRearLightOff_ReturnsProperPayload(ushort deviceId, ushort appId,
byte v1, byte v2, byte v4, byte sequence)
{
// arrange
var encoder = Create(deviceId, appId, sequence: sequence); // speed and steering are zero, so the sequence is not incremented

// act
var result = encoder.EncodeValues([Zero, Zero, One, Zero]);

// assert
result.Length.Should().Be(16);
result.ToArray().Should().BeEquivalentTo(
[
0xBB, 0x11, 0x11,
(byte)(deviceId & 0xFF), (byte)((deviceId >> 8) & 0xFF),
(byte)(appId & 0xFF), (byte)((appId >> 8) & 0xFF),
v1, v2, 0b01, v4,
sequence, 0xCC, 0xB8, 0x92, 0xB0
]);
}

[Theory]
[InlineData(0xC1C9, 0x2979, 0x4B, 0x4B, 0xCB, 0xFA)] // bb 11 11 c9 c1 79 29 4b 4b 03 cb fa cc b8 92 b0
public void EncodeValues_WithZeroValuesAndFrontLightOffAndRearLightOn_ReturnsProperPayload(ushort deviceId, ushort appId,
byte v1, byte v2, byte v4, byte sequence)
{
// arrange
var encoder = Create(deviceId, appId, sequence: sequence); // speed and steering are zero, so the sequence is not incremented

// act
var result = encoder.EncodeValues([Zero, Zero, Zero, One]);

// assert
result.Length.Should().Be(16);
result.ToArray().Should().BeEquivalentTo(
[
0xBB, 0x11, 0x11,
(byte)(deviceId & 0xFF), (byte)((deviceId >> 8) & 0xFF),
(byte)(appId & 0xFF), (byte)((appId >> 8) & 0xFF),
v1, v2, 0b10, v4,
sequence, 0xCC, 0xB8, 0x92, 0xB0
]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void Encode_WithValidInput_ReturnsCorrectLengthAndStaticStructure()
var encoder = Create(0x4032, [0x01, 0x23, 0x40], [0x87, 0x65, 0x43]);

// Act
var result = encoder.Encode([Zero, Zero, Zero]);
var result = encoder.Encode([Zero, Zero, Zero, Zero]);

// Assert
result.Length.Should().Be(16);
Expand All @@ -43,18 +43,74 @@ public void Encode_WithFullLightValue_EncodesAndEncryptsValues()
var encoder = Create(0x4032, [0x01, 0x02, 0x03], [0x04, 0x05, 0x06]);

// Act
var result = encoder.Encode([Zero, Zero, One]);
var result = encoder.Encode([Zero, Zero, One, One]);

// Assert
result.Length.Should().Be(16);
result.Should().EndWith([0xD6, 0xA4, 0x25, 0x89, 0x4E, 0x6D, 0x25, 0x25]);
result.Should().EndWith([
0xD6,
0xA4,
0x25, // [10] ChannelData verticalValue (min= 0x80 (128))
0x89, // [11] ChannelData horizontalValue (min= 0x80 (128))
0x26, // [12] ChannelData lightValue
0x6D, // [13] ChannelData
0x25, // [14] ChannelData
0x25 // [15] ChannelData
]);
}

[Fact]
public void Encode_WithFrontLightValue_EncodesAndEncryptsValues()
{
// Arrange
var encoder = Create(0x4032, [0x01, 0x02, 0x03], [0x04, 0x05, 0x06]);

// Act
var result = encoder.Encode([Zero, Zero, One, Zero]);

// Assert
result.Length.Should().Be(16);
result.Should().EndWith([
0xD6,
0xA4,
0x25, // [10] ChannelData verticalValue (min= 0x80 (128))
0x89, // [11] ChannelData horizontalValue (min= 0x80 (128))
0x24, // [12] ChannelData lightValue
0x6D, // [13] ChannelData
0x25, // [14] ChannelData
0x25 // [15] ChannelData
]);
}

[Fact]
public void Encode_WithRearLightValue_EncodesAndEncryptsValues()
{
// Arrange
var encoder = Create(0x4032, [0x01, 0x02, 0x03], [0x04, 0x05, 0x06]);

// Act
var result = encoder.Encode([Zero, Zero, Zero, One]);

// Assert
result.Length.Should().Be(16);
result.Should().EndWith([
0xD6,
0xA4,
0x25, // [10] ChannelData verticalValue (min= 0x80 (128))
0x89, // [11] ChannelData horizontalValue (min= 0x80 (128))
0x27, // [12] ChannelData lightValue
0x6D, // [13] ChannelData
0x25, // [14] ChannelData
0x25 // [15] ChannelData
]);
}

[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(2)]
[InlineData(4)]
[InlineData(3)]
[InlineData(5)]
[InlineData(10)]
public void Encode_WithInvalidValueCount_ThrowsArgumentException(int count)
{
Expand All @@ -76,7 +132,7 @@ public void EncodeValues_WithZeros_ShouldEncodeCorrectly()
// Arrange
var encoder = Create(0xABCD, [0x01, 0x02, 0x03], [0x04, 0x05, 0x06]);
// Act
var result = encoder.EncodeValues([Zero, Zero, Zero]);
var result = encoder.EncodeValues([Zero, Zero, Zero, Zero]);
// Assert
result.Length.Should().Be(8);
result.ToArray().Should().Equal(
Expand All @@ -85,45 +141,43 @@ public void EncodeValues_WithZeros_ShouldEncodeCorrectly()
0xAB, // [9] ChannelData random
0x80, // [10] ChannelData verticalValue (min= 0x80 (128))
0x80, // [11] ChannelData horizontalValue (min= 0x80 (128))
0x80, // [12] ChannelData lightValue
0x00, // [12] ChannelData lightValue
0x00, // [13] ChannelData
0x00, // [14] ChannelData
0x00, // [15] ChannelData
]);
}

[Theory]
[InlineData(-2.0f, 1.0f, 1.0f)] // Out of range speed
[InlineData(-1.0f, 2.0f, 1.0f)] // Out of range steering
[InlineData(-1.0f, 1.0f, 2.0f)] // Out of range light
public void Encode_WithOutOfRangeValues_ClampsTo0xFF(float speed, float steering, float light)
[InlineData(-2.0f, 1.0f)] // Out of range speed
[InlineData(-1.0f, 2.0f)] // Out of range steering
public void Encode_WithOutOfRangeValues_ClampsTo0xFF(float speed, float steering)
{
// Arrange
var encoder = Create();
// Act
var result = encoder.EncodeValues([(Half)speed, (Half)steering, (Half)light]);
var result = encoder.EncodeValues([(Half)speed, (Half)steering, Zero, Zero]);
// Assert
result.ToArray().Should().EndWith(
[
0xFF, // [10] ChannelData verticalValue (min= 0x80 (128))
0xFF, // [11] ChannelData horizontalValue (min= 0x80 (128))
0xFF, // [12] ChannelData lightValue
0x00, // [12] ChannelData lightValue
0x00, // [13] ChannelData
0x00, // [14] ChannelData
0x00, // [15] ChannelData
]);
}

[Theory]
[InlineData(2.0f, -1.0f, -1.0f)] // Out of range speed
[InlineData(1.0f, -2.0f, -1.0f)] // Out of range steering
[InlineData(1.0f, -1.0f, -2.0f)] // Out of range light
public void Encode_WithOutOfRangeValues_ClampsTo0x00(float speed, float steering, float light)
[InlineData(2.0f, -1.0f)] // Out of range speed
[InlineData(1.0f, -2.0f)] // Out of range steering
public void Encode_WithOutOfRangeValues_ClampsTo0x00(float speed, float steering)
{
// Arrange
var encoder = Create();
// Act
var result = encoder.EncodeValues([(Half)speed, (Half)steering, (Half)light]);
var result = encoder.EncodeValues([(Half)speed, (Half)steering, Zero, Zero]);
// Assert
result.ToArray().Should().EndWith(
[
Expand Down
Loading