I'm reading range/distance sensor data from one Serial Port, decoding it and then transmitting it to a secondary device in ASCII format. The sensor uses a 2-byte header with each byte containing the following hex values: 0x59 0x59. Additional data from the sensor is also sent in a 7-byte message, subsequent to the header.
The code works but I'm not convinced that I'm reading the data correctly in DataReceived event handler. How can I improve this code?
internal static class Program
{
private static long _validMessageCount;
private static SerialPort _distanceOutputSerialPort;
private const int FrameHeader = 0x59;
public static void Main()
{
SerialPort lidarSensorSerialPort = null;
try
{
lidarSensorSerialPort = new SerialPort(AppSettings.InputPort)
{
BaudRate = AppSettings.InputBaudRate,
DataBits = AppSettings.InputDataBits,
Handshake = Handshake.None,
Parity = Parity.None,
StopBits = StopBits.One
};
_distanceOutputSerialPort = new SerialPort(AppSettings.OutputPort)
{
BaudRate = AppSettings.OutputBaudRate,
DataBits = AppSettings.OutputDataBits,
Handshake = Handshake.None,
Parity = Parity.None,
StopBits = StopBits.One,
NewLine = "\r",
Encoding = Encoding.ASCII
};
_distanceOutputSerialPort.Open();
lidarSensorSerialPort.DataReceived += DataReceivedHandler;
lidarSensorSerialPort.Open();
Console.Write("Waiting for data...");
Console.ReadKey();
}
catch (IOException e)
{
Console.WriteLine(e.Message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
lidarSensorSerialPort?.Close();
_distanceOutputSerialPort?.Close();
Console.Write("Press any key to exit...");
Console.ReadKey();
}
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
var headerBytes = new byte[2];
var measuredRangeBytes = new byte[7];
var serialPort = (SerialPort) sender;
if (serialPort.BytesToRead < 9)
return;
while (true)
{
if (headerBytes[0] == FrameHeader && headerBytes[1] == FrameHeader)
break;
serialPort.Read(headerBytes, 0, headerBytes.Length);
}
var bytesRead = serialPort.Read(measuredRangeBytes, 0, measuredRangeBytes.Length);
if (bytesRead < measuredRangeBytes.Length)
{
Console.WriteLine($"Invalid data Received. [{bytesRead}]");
return;
}
var completeBytes = headerBytes.Concat(measuredRangeBytes).ToArray();
var checksum = Helpers.CalculateChecksum(completeBytes);
var check = measuredRangeBytes[6];
if (checksum != check)
{
Console.WriteLine("Invalid Checksum");
return;
}
CalculateDistance(measuredRangeBytes);
}
private static void CalculateDistance(IList<byte> distanceBytes)
{
var distanceLow = distanceBytes[0];
var distanceHigh = distanceBytes[1];
var strengthLow = distanceBytes[2];
var strengthHigh = distanceBytes[3];
var realibilityLevel = distanceBytes[4];
var exposureTime = distanceBytes[5];
var distance = Math.Round(distanceHigh * 256d + distanceLow, 2);
var strength = strengthHigh * 256 + strengthLow;
var time = $"{DateTime.Now:HH:mm:ss.fff}";
_validMessageCount++;
Console.WriteLine(
$"{_validMessageCount}. {time} | {distance} | {strength} | {realibilityLevel} | {exposureTime}");
ConvertOuput(distance);
}
private static void ConvertOuput(double distance)
{
var distanceInMeters = Math.Round(distance / 100d, 2);
var mdlLmSensorOutput = $"{distanceInMeters.ToString("F").PadLeft(6, '0')}m";
_distanceOutputSerialPort.WriteLine(mdlLmSensorOutput);
Console.WriteLine($"Output: {mdlLmSensorOutput}");
}
}