开发者

How can I simulate SerialPort interactions for testing?

开发者 https://www.devze.com 2023-02-25 13:34 出处:网络
I\'m about to start developing a small app (C#) that communicates with a PLC and a testing unit via Serial Ports - this is my first venture into this area.

I'm about to start developing a small app (C#) that communicates with a PLC and a testing unit via Serial Ports - this is my first venture into this area.

In essence, I am going to send the PLC a signal to start an operation, and then I am going to wait for the result of that operation from the test unit (which will be independently communicating with the PLC) to return a ASCII string.

Depending on the content of that string, I may want to listen to a signal from the PLC...

It's all new to me, so at the moment, I'm just researching System.IO.Ports.SerialPort; digression: are there third part products out there than simplify interaction with the Serial Port, or are the built-in classes as good as you will get? I'm thinking of ease of use as opposed to better features.

However, it will be a few weeks before the hardware is available for development and testing, so I was wondering how I could simulate communication to/from the serial port so that I can start developing my app?

[I don't yet know how the PLC and the PC are due to communicate - I understand it wil开发者_运维问答l be binary rather than text, but at the moment, that is all I know.]


Abstract away your serial port comms behind an interface so that you can code your app against the interface and then test with a 'fake' implementation. When you've got the hardware for the real thing, you can code up the 'real' implementation of the interface and swap out the fake one.

So for example, you'd have an interface

public interface ISerialComms
{
    void SendMessage(string message)
}

and you'd code your app against that interface using a fake implementation:

public class FakeSerialComms : ISerialComms
{
    public void SendMessage(string message)
    {
        //some implementation
    }
}

Hope that helps!


I've had some success in the past using com0com.


There are two pieces of software that I have found invaluable while doing serial port work.

Free Serial Port Monitor

http://www.serial-port-monitor.com

Despite the cheesy name, it is actually quite useful. Note that you should have it stop listening to your port if you go to unplug a USB-to-Serial converter. Otherwise it can crash (well... wait indefinitely on exit, which is annoying). It doesn't have to put itself in the middle of a serial connection to sniff data. It monitors the IO using the Win32 API.

Franson Serial Port Tools

http://franson.com/serialtools/

Or.. any loopback software really. There are lots out there. This allows you to send data and receive it within software. If you end up doing any GPS work, Franson also has a nice GPS simulator so you don't have to sit outside the whole time to debug code.


Finally, if you have had enough with the built-in serial class and its horrendous shortcomings, then you need a replacement, and going straight to the Win32 API will take forever.

CommStudio

I have found CommStudio to be absolutely rock solid. Quite frankly, after spending 5 months researching and buying other options, it is the only one that works perfectly with removable USB adapters. All of the other solutions have issues when the device is plugged back in. You can download their free "Express" version here: http://www.componentsource.com/products/commstudio/downloads.html?rv=42917


I have wrote an article on this topic using Virtual Serial Port Driver 9.0 standard using Microsoft SerialPort Class (Sytem.IO.Ports), it is of course possible to use any other comm port tool.

In the software I create 2 virtual ports COM1 and COM2.

I use COM1 to emulate as data sender.

I use COM2 to receive what ever being send from COM1.

This is helpful if you are developing Embedded or IoT solution.

Emulator (in this example as random accelerometer)

private static bool _continue;
private static SerialPort _serialPort;

public static void Main()
{
    var stringComparer = StringComparer.OrdinalIgnoreCase;
    var readThread = new Thread(Read);

    _serialPort = new SerialPort
    {
        PortName = "COM1",
        ReadTimeout = 500,
        WriteTimeout = 500
    };

    _serialPort.Open();
    _continue = true;
    readThread.Start();

    while (_continue)
    {
        var x = ValueGenerator();
        var y = ValueGenerator();
        var z = ValueGenerator();
        var message = $"x:{x};y:{y};z:{z}";

        if (stringComparer.Equals("quit", message))
        {
            _continue = false;
        }
        else
        {
            _serialPort.WriteLine(message);
            Thread.Sleep(200);
        }
    }

    readThread.Join();
    _serialPort.Close();
}

public static double ValueGenerator()
{
    const int range = 1;
    var random = new Random();
    return random.NextDouble() * range;
}

public static void Read()
{
    while (_continue)
    {
        try
        {
            var message = _serialPort.ReadLine();
            Console.WriteLine(message);
        }
        catch (TimeoutException) { }
    }
}

And my data receiver is almost similar

private static bool _continue;
private static SerialPort _serialPort;

public static void Main()
{
    var stringComparer = StringComparer.OrdinalIgnoreCase;
    var readThread = new Thread(Read);

    _serialPort = new SerialPort
    {
        PortName = "COM2",
        ReadTimeout = 500,
        WriteTimeout = 500
    };

    _serialPort.Open();
    _continue = true;
    readThread.Start();

    while (_continue)
    {
        var message = Console.ReadLine();

        if (stringComparer.Equals("quit", message))
        {
            _continue = false;
        }
        else
        {
            _serialPort.WriteLine(message);
        }
    }

    readThread.Join();
    _serialPort.Close();
}

public static void Read()
{
    while (_continue)
    {
        try
        {
            var message = _serialPort.ReadLine();
            Console.WriteLine(message);
        }
        catch (TimeoutException) { }
    }
}

Disclaimer: the link of this guideline refer to my personal web site.


I like David's answer above but if your looking to do integration tests and actually test your serial port communication I have used and application called ViN soft virtual serial cable in the past to basically create 2 serial ports on your machine that are connected by a virtual cable.

Also if you have a serial port on your development machine you could use it to connect to another machine that has a serial port and write an application that will basically simulate the communication of the PLC.

I would prefer to use a combination of both David's method and this method to ensure proper testing.


There is another resource out there that emulates serial ports for windows if anyone else is still looking for decent serial debugging tools.

The 32-bit version is free and seems pretty decent. It's called Virtual Serial Ports Emulator.


Very old but still might be useful to some. Instead of relying on COM interaction, just use the SerialPort.BaseStream to communicate with the port. This allows you to simply use a standard stream interface for communication, in other words, doesn't matter if you use serial ports, TCP connections, or even file streams. Perfect for simulation.

0

精彩评论

暂无评论...
验证码 换一张
取 消