【问题标题】:How can I simulate SerialPort interactions for testing?如何模拟 SerialPort 交互以进行测试?
【发布时间】:2011-08-03 22:34:44
【问题描述】:

我即将开始开发一个小型应用程序 (C#),它通过串行端口与 PLC 和测试单元通信 - 这是我第一次涉足该领域。

本质上,我将向 PLC 发送一个信号以开始操作,然后我将等待来自测试单元(它将与 PLC 独立通信)的操作结果返回一个ASCII 字符串。

根据该字符串的内容,我可能想收听来自 PLC 的信号...

这对我来说是全新的,所以目前我只是在研究 System.IO.Ports.SerialPort;题外话:是否有第三方产品可以简化与串行端口的交互,或者内置类是否与您将获得的一样好?我考虑的是易用性,而不是更好的功能。

但是,硬件可用于开发和测试还需要几周时间,所以我想知道如何模拟与串行端口的通信,以便开始开发我的应用程序?强>

[我还不知道 PLC 和 PC 是如何通信的 - 我知道它将是二进制而不是文本,但目前我只知道这些。]

【问题讨论】:

  • 在为我的 Arduino 编写一些应用程序时,我一直想知道这一点。据我所知,在串行端口上真正模拟数据的唯一方法是使用硬件环回设备(那里有自己制作的说明,而且并不难)。下面的界面答案是一个不错的选择。

标签: c# serial-port simulation


【解决方案1】:

非常古老,但对某些人可能仍然有用。无需依赖 COM 交互,只需使用 SerialPort.BaseStream 与端口进行通信。这使您可以简单地使用标准流接口进行通信,换句话说,无论您使用串行端口、TCP 连接还是文件流都无关紧要。非常适合模拟。

【讨论】:

    【解决方案2】:

    我过去曾使用com0com 取得过一些成功。

    【讨论】:

    • +1 我实际上回去使用了它,它比我在下面建议的应用程序效果更好。无论出于何种原因,我在下面建议的应用似乎都会阻止对这些端口的所有调用。
    • 注意:我将链接更改为实际项目页面而不是 com0com.sourceforge.net:该链接部分被 Eltima Software 的虚拟串行端口驱动程序“接管”。该软件没有任何问题,但我们不想引诱人们点击他们的下载链接而不是 com0com 的链接,而且它属于单独的答案。
    • 附加说明:com0com 可以工作,但请阅读自述文件:在撰写本文时,在最近的 Windows 版本上安装将导致驱动程序无法加载,因为它缺少签名,因此您需要禁用“驱动程序签名强制” " 即相当于bcdedit.exe -set TESTSIGNING ON。使用风险自负。
    【解决方案3】:

    我已经使用 Microsoft SerialPort 类 (Sytem.IO.Ports) 的 Virtual Serial Port Driver 9.0 标准就这个主题写了一个article,当然可以使用任何其他通信端口工具。

    在软件中,我创建了 2 个虚拟端口 COM1 和 COM2。

    我使用 COM1 模拟为数据发送器。

    我使用 COM2 接收从 COM1 发送的内容。

    如果您正在开发嵌入式或物联网解决方案,这将很有帮助。

    模拟器(在本例中为随机加速度计)

    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) { }
        }
    }
    

    和我的数据接收器差不多

    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) { }
        }
    }
    

    免责声明:本指南链接指向我的个人网站。

    【讨论】:

      【解决方案4】:

      如果其他人仍在寻找体面的串行调试工具,还有另一种资源可以模拟 Windows 的串行端口。

      32 位版本是免费的,看起来相当不错。它叫做Virtual Serial Ports Emulator

      【讨论】:

        【解决方案5】:

        在进行串行端口工作时,我发现有两个软件非常宝贵。

        免费串口监视器

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

        尽管名字俗气,但实际上非常有用。请注意,如果您要拔下 USB 转串口转换器,您应该让它停止监听您的端口。否则它可能会崩溃(嗯......无限期地等待退出,这很烦人)。它不必将自己置于串行连接的中间来嗅探数据。它使用 Win32 API 监控 IO。

        Franson 串口工具

        http://franson.com/serialtools/

        或者.. 任何环回软件。那里有很多。这允许您在软件中发送和接收数据。如果您最终从事任何 GPS 工作,Franson 也有一个不错的 GPS 模拟器,因此您不必一直坐在外面调试代码。


        最后,如果您已经受够了内置的串行类及其可怕的缺点,那么您需要一个替代品,而直接使用 Win32 API 将需要很长时间。

        CommStudio

        我发现CommStudio 绝对坚如磐石。坦率地说,在花了 5 个月的时间研究和购买其他选项之后,它是唯一一款与可移动 USB 适配器完美配合的选项。当设备重新插入时,所有其他解决方案都会出现问题。您可以在此处下载他们的免费“Express”版本:http://www.componentsource.com/products/commstudio/downloads.html?rv=42917

        【讨论】:

          【解决方案6】:

          我喜欢上面 David 的回答,但如果您希望进行集成测试并实际测试您的串行端口通信,我过去曾使用过称为 ViN 软虚拟串行电缆的应用程序基本上在您的机器上创建 2 个串行端口,它们通过以下方式连接一条虚拟电缆。

          此外,如果您的开发机器上有串行端口,您可以使用它连接到另一台具有串行端口的机器,并编写一个基本上模拟 PLC 通信的应用程序。

          我更喜欢结合使用 David 的方法和这种方法来确保正确的测试。

          【讨论】:

          • 我有其他机器可用,因此在其中一台机器上运行测试应用程序是完全可能的,这是我的后备位置。我也会查看 ViN 软件应用程序。谢谢
          【解决方案7】:

          抽象出接口后面的串行端口通信,以便您可以针对该接口编写应用程序,然后使用“假”实现进行测试。当您拥有真正的硬件后,您可以编写接口的“真实”实现并换掉假的。

          例如,你会有一个界面

          public interface ISerialComms
          {
              void SendMessage(string message)
          }
          

          然后您会使用虚假实现针对该接口编写您的应用程序:

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

          希望有帮助!

          【讨论】:

          • 我喜欢这个解决方案。对于集成测试,尽管我经常发现除非我在客户现场,否则我无法访问正在与之交互的设备。这在一定程度上限制了我有效进行集成测试的能力,除非我编写某种模拟器。
          • @Cole 当然,它在某些时候需要某种模拟器,但对于开始使用界面应该足够了。 @n8wrl 是的,当然,应该提到这一点! :)
          • 以前没有做过这样的事情,但很有意义......如果我能弄清楚该怎么做的话。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-08-26
          • 2021-11-25
          • 2013-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多