Add protocolCommons classes and enhance RadioService with support for CalibrationFactor, VersionType, ReadingUnits, and FlipMode operations. Add corresponding unit tests for validation. Update project files.
155 lines
5.5 KiB
C#
155 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol
|
|
{
|
|
public sealed class IperlHatFrameParser
|
|
{
|
|
|
|
public IperlHatResponse Parse(byte[] data)
|
|
{
|
|
if (data == null)
|
|
throw new ArgumentNullException(nameof(data));
|
|
|
|
if (data.Length < 5)
|
|
throw new FormatException("Frame too short.");
|
|
|
|
|
|
|
|
if (data[0] != TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Start)
|
|
{
|
|
//if version parse version
|
|
if (data[0] == TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question)
|
|
{
|
|
//Define Question answer
|
|
var prefix = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question };
|
|
var end = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.End };
|
|
|
|
if (IsPrefixValid(data, prefix, end))
|
|
{
|
|
//whole payload may be like "vers: Harry T:B800, V:06.06.01, FW:190215, 7ECE, B1.6.01, HW:4, Serial:0"
|
|
prefix = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question };
|
|
byte[] payloadVersion = ExtractPayloadUsePrefix(data, prefix, end);
|
|
return new IperlHatResponse(TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question, payloadVersion.Length > 0 ? TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.StatusOk : TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.StatusNok, payloadVersion);
|
|
}
|
|
}
|
|
|
|
throw new FormatException("Invalid START byte.");
|
|
}
|
|
|
|
if (data[1] != TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Read)
|
|
throw new FormatException("Frame is no Response.");
|
|
|
|
byte length = data[2];
|
|
if (length != data.Length)
|
|
throw new FormatException("Length mismatch.");
|
|
|
|
byte direction = data[1];
|
|
byte status = data[3];
|
|
|
|
var prefixCommand = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Start,direction,length,status };
|
|
var endCommand = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.End };
|
|
|
|
byte[] payload = ExtractPayloadUsePrefix(data,prefixCommand,endCommand);
|
|
|
|
return new IperlHatResponse(0x00, status, payload);
|
|
}
|
|
|
|
|
|
private static byte[] ExtractPayloadUsePrefix(
|
|
byte[] data,
|
|
List<byte> prefix,
|
|
List<byte> end)
|
|
{
|
|
if (!IsPrefixValid(data, prefix, end))
|
|
return Array.Empty<byte>();
|
|
|
|
int payloadLength = data.Length - (prefix.Count + end.Count);
|
|
|
|
if (payloadLength <= 0)
|
|
return Array.Empty<byte>();
|
|
|
|
byte[] payload = new byte[payloadLength];
|
|
|
|
Buffer.BlockCopy(
|
|
data,
|
|
prefix.Count,
|
|
payload,
|
|
0,
|
|
payloadLength);
|
|
|
|
return payload;
|
|
}
|
|
|
|
private static bool IsPrefixValid(
|
|
byte[] data,
|
|
List<byte> prefix,
|
|
List<byte> end)
|
|
{
|
|
if (data == null ||
|
|
prefix == null ||
|
|
end == null ||
|
|
data.Length < prefix.Count + end.Count)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Check frame prefix.
|
|
byte[] commandPrefix = new byte[prefix.Count];
|
|
|
|
Buffer.BlockCopy(
|
|
data,
|
|
0,
|
|
commandPrefix,
|
|
0,
|
|
prefix.Count);
|
|
|
|
if (!StartsWithPrefix(prefix, commandPrefix))
|
|
return false;
|
|
|
|
// Check frame ending.
|
|
byte[] commandEnd = new byte[end.Count];
|
|
|
|
Buffer.BlockCopy(
|
|
data,
|
|
data.Length - end.Count,
|
|
commandEnd,
|
|
0,
|
|
end.Count);
|
|
|
|
if (!StartsWithPrefix(end, commandEnd))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
private static bool StartsWithPrefix(List<byte> data, byte[] prefix)
|
|
{
|
|
if (data.Count < prefix.Length)
|
|
return false;
|
|
|
|
for (int i = 0; i < prefix.Length; i++)
|
|
{
|
|
if (data[i] != prefix[i])
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static byte[] ExtractVersionPayload(byte[] data)
|
|
{
|
|
// payload exists only if frame longer than:
|
|
// START + LEN + CTRL + STATUS + CHK_HI + CHK_LO = 6 bytes
|
|
if (data.Length <= 5)
|
|
return Array.Empty<byte>();
|
|
|
|
int payloadLength = data.Length - 4;
|
|
byte[] payload = new byte[payloadLength];
|
|
Buffer.BlockCopy(data, 5, payload, 0, payloadLength);
|
|
return payload;
|
|
}
|
|
}
|
|
|
|
|
|
} |