Use System.IO.Ports.SerialPort.
https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport?view=net-8.0
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
How can data be read from a device connected to a computer via a COM port using a .NET console application? The device measures the weight of heavy vehicles and is connected to a weigher that displays the results. The existing application on the computer is outdated, and support is unavailable. Any guidance would be appreciated.
I appreciate any help you can provide.
There is the SerialPort class. However, bear in mind that it's not held in high regard!
Use System.IO.Ports.SerialPort.
https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport?view=net-8.0
Hi,
In my console application I am setting connection parameters as follows;
public async Task StartMeasuringAsync(CancellationToken cancellationToken)
{
const int baudRate = 1200;
var availablePorts = SerialPort.GetPortNames();
if (availablePorts.Length == 0)
{
LogWithColor("No COM ports are available.\n", ConsoleColor.Red);
return;
}
LogWithColor($"Available COM ports: {string.Join(", ", availablePorts)}\n", ConsoleColor.Green);
foreach (var portName in availablePorts)
{
LogWithColor($"Attempting to connect to {portName} at {baudRate} baud\n", ConsoleColor.Yellow);
try
{
_serialPort = new SerialPort(portName, baudRate)
{
DataBits = 8,
Parity = Parity.None,
StopBits = StopBits.One,
Handshake = Handshake.None,
};
_serialPort.Open();
...
Should I also need to change the connection parameters on the device manager?
Should I also need to change the connection parameters on the device manager?
It is not necessary to match them, but if any problems arise, matching the properties may resolve them.
The weird thing is I can't read the raw data from the PWI-T device. Is there a tool that I can install to my Windows machine in order to monitor serial port data?
Putty
https://www.putty.org/
I downloaded Realterm, hope I can monitor device data with it :)
Are there any updates?
I have a problem with the driver of the RS232 - USB connector. Bought a new one with a driver included. When I get it, I will try and let you know.
Ok, I'll wait for your update.
Even though I bought a new RS232 - USB connector and installed it successfully, I couldn't get the data from the device. I tried Realterm but no data is coming surprisingly. The parameters are correct with the device but somehow no data is captured.
Here is the updated code for my situation:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.IO.Ports;
using System.Text;
using System.Text.Json;
namespace VehicleWeightMeasurement;
public class WeightMeasurementService : IDisposable
{
private readonly ILogger<WeightMeasurementService> _logger;
private readonly IConfiguration _configuration;
private SerialPort? _serialPort;
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
private bool _dataReceived = false;
private readonly string _clientId;
public WeightMeasurementService(ILogger<WeightMeasurementService> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
_serialPort = null;
_clientId = _configuration["ClientId"] ?? Guid.NewGuid().ToString(); // Get from config or generate
}
public async Task StartMeasuringAsync(CancellationToken cancellationToken)
{
const int baudRate = 1200;
var availablePorts = SerialPort.GetPortNames();
if (availablePorts.Length == 0)
{
LogWithColor("No COM ports are available.\n", ConsoleColor.Red);
return;
}
LogWithColor($"Available COM ports: {string.Join(", ", availablePorts)}\n", ConsoleColor.Green);
foreach (var portName in availablePorts)
{
LogWithColor($"Attempting to connect to {portName} at {baudRate} baud\n", ConsoleColor.Yellow);
try
{
_serialPort = new SerialPort("COM5", baudRate)
{
DataBits = 8,
Parity = Parity.None,
StopBits = StopBits.One,
Handshake = Handshake.None,
};
_serialPort.Open();
LogWithColor($"*** Successfully *** connected to {_serialPort.PortName} at {baudRate} baud\n", ConsoleColor.Green);
_serialPort.DataReceived += SerialPort_DataReceived;
// Continuously listen for valid data reception
while (!cancellationToken.IsCancellationRequested)
{
if (_dataReceived)
{
LogWithColor("Valid weight data received successfully.\n", ConsoleColor.Green);
_dataReceived = false; // Reset flag for next data reception
}
await Task.Delay(4500, cancellationToken); // Adjust delay as necessary
}
}
catch (UnauthorizedAccessException)
{
LogWithColor($"Access to the port {portName} is denied. The port may be in use by another application.\n", ConsoleColor.Red);
}
catch (IOException)
{
LogWithColor($"An I/O error occurred while accessing the port {portName}.\n", ConsoleColor.Red);
}
catch (Exception)
{
LogWithColor("An unexpected error occurred while starting measurement.\n", ConsoleColor.Red);
}
finally
{
ClosePort();
}
}
LogWithColor("Failed to receive valid weight data from any port.\n", ConsoleColor.Red);
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
LogWithColor("DataReceived event triggered.\n", ConsoleColor.Cyan);
if (_cts.IsCancellationRequested) return;
try
{
if (_serialPort == null || _serialPort.BytesToRead <= 0) return;
// Read the bytes from the serial port
byte[] buffer = new byte[_serialPort.BytesToRead];
_serialPort.Read(buffer, 0, buffer.Length);
// Convert the bytes to a string
string data = BitConverter.ToString(buffer).Replace("-", string.Empty);
LogWithColor($"Raw data received: {data}\n", ConsoleColor.Cyan);
// Parse the data according to the specified format
if (TryParseWeightData(data, out float weight))
{
_dataReceived = true;
ProcessWeight(weight);
}
else
{
LogWithColor($"Received unexpected data format: {data}\n", ConsoleColor.Yellow);
}
}
catch (TimeoutException)
{
LogWithColor("Timeout occurred while reading from serial port.\n", ConsoleColor.Yellow);
}
catch (Exception)
{
LogWithColor("Error processing received data.\n", ConsoleColor.Red);
}
}
private async void ProcessWeight(float weight)
{
var minWeight = float.Parse(_configuration["WeightLimits:MinWeight"] ?? string.Empty);
var maxWeight = float.Parse(_configuration["WeightLimits:MaxWeight"] ?? string.Empty);
if (weight < minWeight)
{
LogWithColor($"Weight below minimum: {weight} kg\n", ConsoleColor.Yellow);
}
else if (weight > maxWeight)
{
LogWithColor($"Weight above maximum: {weight} kg\n", ConsoleColor.Yellow);
}
else
{
LogWithColor($"Valid weight measured: {weight} kg\n", ConsoleColor.Green);
}
// Send the weight data to the web API
var measurement = new { Value = weight, Unit = "Kg", Timestamp = DateTime.Now, ClientId = _clientId, PlateNumber = "06AB001", VehicleType = "Truck" };
var httpClient = new HttpClient();
var content = new StringContent(JsonSerializer.Serialize(measurement), Encoding.UTF8, "application/json");
await httpClient.PostAsync("https://localhost:7008/api/Measurements", content);
// Wait for a random time between 1 and 5 seconds
await Task.Delay(new Random().Next(5000, 20000));
// Send the weight data to the web API
measurement = new { Value = weight - 1000, Unit = "Kg", Timestamp = DateTime.Now, ClientId = "Yeşilköy", PlateNumber = "34DE002", VehicleType = "Van" };
httpClient = new HttpClient();
content = new StringContent(JsonSerializer.Serialize(measurement), Encoding.UTF8, "application/json");
await httpClient.PostAsync("https://localhost:7008/api/Measurements", content);
}
private void ClosePort()
{
if (_serialPort?.IsOpen == true)
{
_serialPort.DataReceived -= SerialPort_DataReceived;
_serialPort.Close();
_serialPort.Dispose();
LogWithColor("Serial port closed and disposed.\n", ConsoleColor.Green);
}
}
public void Dispose()
{
_cts.Cancel();
ClosePort();
}
private void LogWithColor(string message, ConsoleColor color)
{
// Include color information in the message
var coloredMessage = $"[Color:{color}] {message}";
// Fallback to default logging if the logger is not SimpleConsoleLogger
_logger.Log(LogLevel.Information, coloredMessage);
}
private bool TryParseWeightData(string data, out float weight)
{
weight = 0;
// Check if the data length is 16 characters (8 bytes in HEX) and ends with '0D' (CR in HEX)
if (data.Length != 16 || !data.EndsWith("0D"))
{
return false;
}
// Convert HEX to ASCII
string asciiData = string.Empty;
for (int i = 0; i < data.Length - 2; i += 2)
{
asciiData += (char)Convert.ToByte(data.Substring(i, 2), 16);
}
// Extract the sign and the numeric part
char sign = asciiData[0];
string numericPart = asciiData.Substring(1, 6);
// Check if the sign is valid
if (sign != '+' && sign != '-')
{
return false;
}
// Try to parse the numeric part as a float
if (float.TryParse(numericPart, out float parsedWeight))
{
// Apply the sign to the parsed weight
weight = sign == '+' ? parsedWeight : -parsedWeight;
return true;
}
return false;
}
}