zoukankan      html  css  js  c++  java
  • C# 构建S7服务器 西门子的虚拟服务器 测试通讯 HslCommunication应用

    本文将使用一个gitHub开源的组件技术来实现S7服务器的功能,使用的是基于以太网的TCP/IP实现,不需要额外的组件

    github地址:https://github.com/dathlin/HslCommunication      fork      star                 如果喜欢可以star或是fork,还可以打赏支持。

    官网地址:http://www.hslcommunication.cn/

    联系作者及加群方式:http://www.hslcommunication.cn/Cooperation 


    演示的demo,快速开发,下载demo程序,您可以进行初步的访问的测试,免去了您写测试程序的麻烦,快速实验通讯,测试开发软件的操作。

    下载地址为:HslCommunicationDemo.zip 

    演示的服务器截图为:

    再配合本组件支持的客户端通讯、就可以实现自我测试。

     两者的地址格式是一致的。

    服务器端支持4种地址:输入的I0,输出的Q0,中间寄存器M100,DB块,DB1.100

    自定义服务器开发


    实际的场景中,很有可能你需要的是一个可以测试的demo,当你在开发上位机,SCADA软件,监控软件,历史追述软件的时候,还没有PLC来给你测试,开发,这时候就可以使用本demo来实现模拟服务器的功能。

    当然还有另一种需求,当你要集成一个服务器到你自己的程序中的时候,就可以使用本组件来实现,而要集成一个自定义的服务器将会是非常的简单。

    1. 安装组件,可以通过下面的指令,或是nuget可视化的客户端来安装

    Install-Package HslCommunication
    

    2. 引用命名空间:

    using HslCommunication.Profinet.Siemens;
    using HslCommunication;
    

    3. 写代码。这个服务器可以是在你的窗体中,当然也可以在你的自定义类中,下面的举例在类中定义(窗体的本质也是类)

            private SiemensS7Server s7NetServer;
            public void S7Start()
            {
                try
                {
                    s7NetServer = new SiemensS7Server();
                    s7NetServer.ServerStart(102);
                }
                catch(Exception ex)
                {
                    Console.Write("Failed:" + HslCommunication.BasicFramework.SoftBasic.GetExceptionMessage(ex));
                }
            }
    

    这样就启动了一个最基本的西门子虚拟服务器了。然后就可以用Hsl组件去读写数据了。端口号是102。

    4. 服务器操作数据信息,有了上述的例子后,我们来扩充服务器的功能,比如在服务器端进行读写数据信息。如下的代码举例的一般类型的读写操作说明。

                // 此处以M100寄存器作为示例
                bool bool_M100_0     = s7NetServer.ReadBool("M100.0").Content;
                byte byte_M100       = s7NetServer.ReadByte("M100").Content;         // 读取M100的值
                short short_M100     = s7NetServer.ReadInt16("M100").Content;        // 读取M100-M101组成的字
                ushort ushort_M100   = s7NetServer.ReadUInt16("M100").Content;       // 读取M100-M101组成的无符号的值
                int int_M100         = s7NetServer.ReadInt32("M100").Content;        // 读取M100-M103组成的有符号的数据
                uint uint_M100       = s7NetServer.ReadUInt32("M100").Content;       // 读取M100-M103组成的无符号的值
                float float_M100     = s7NetServer.ReadFloat("M100").Content;        // 读取M100-M103组成的单精度值
                long long_M100       = s7NetServer.ReadInt64("M100").Content;        // 读取M100-M107组成的大数据值
                ulong ulong_M100     = s7NetServer.ReadUInt64("M100").Content;       // 读取M100-M107组成的无符号大数据
                double double_M100   = s7NetServer.ReadDouble("M100").Content;       // 读取M100-M107组成的双精度值
                string string_M100   = s7NetServer.ReadString("M100", 10).Content;   // 读取M100-M109组成的ASCII字符串数据
    
                // 读取数组
                short[] short_M100_array      = s7NetServer.ReadInt16("M100", 10).Content;      // 读取M100-M101组成的字
                ushort[] ushort_M100_array    = s7NetServer.ReadUInt16("M100", 10).Content;     // 读取M100-M101组成的无符号的值
                int[] int_M100_array          = s7NetServer.ReadInt32("M100", 10).Content;      // 读取M100-M103组成的有符号的数据
                uint[] uint_M100_array        = s7NetServer.ReadUInt32("M100", 10).Content;     // 读取M100-M103组成的无符号的值
                float[] float_M100_array      = s7NetServer.ReadFloat("M100", 10).Content;      // 读取M100-M103组成的单精度值
                long[] long_M100_array        = s7NetServer.ReadInt64("M100", 10).Content;      // 读取M100-M107组成的大数据值
                ulong[] ulong_M100_array      = s7NetServer.ReadUInt64("M100", 10).Content;     // 读取M100-M107组成的无符号大数据
                double[] double_M100_array    = s7NetServer.ReadDouble("M100", 10).Content;     // 读取M100-M107组成的双精度值
    

    基本的写入操作

                // 此处以M100寄存器作为示例
                s7NetServer.Write("M100", true);                       // 写入M100  bool值
                s7NetServer.Write("M100", (byte)123);                  // 写入M100  byte值
                s7NetServer.Write("M100", (short)1234);                // 写入M100  short值
                s7NetServer.Write("M100", (ushort)45678);              // 写入M100  ushort值
                s7NetServer.Write("M100", 1234566);                    // 写入M100  int值
                s7NetServer.Write("M100", (uint)1234566);              // 写入M100  uint值
                s7NetServer.Write("M100", 123.456f);                   // 写入M100  float值
                s7NetServer.Write("M100", 123.456d);                   // 写入M100  double值
                s7NetServer.Write("M100", 123456661235123534L);        // 写入M100  long值
                s7NetServer.Write("M100", 523456661235123534UL);       // 写入M100  ulong值
                s7NetServer.Write("M100", "K123456789");               // 写入M100  string值
    
                // 读取数组
                s7NetServer.Write("M100", new short[] { 123, 3566, -123 });                                      // 写入M100  short值  ,W3C0,R3C0 效果是一样的
                s7NetServer.Write("M100", new ushort[] { 12242, 42321, 12323 });                                 // 写入M100  ushort值
                s7NetServer.Write("M100", new int[] { 1234312312, 12312312, -1237213 });                         // 写入M100  int值
                s7NetServer.Write("M100", new uint[] { 523123212, 213, 13123 });                                 // 写入M100  uint值
                s7NetServer.Write("M100", new float[] { 123.456f, 35.3f, -675.2f });                             // 写入M100  float值
                s7NetServer.Write("M100", new double[] { 12343.542312d, 213123.123d, -231232.53432d });          // 写入M100  double值
                s7NetServer.Write("M100", new long[] { 1231231242312, 34312312323214, -1283862312631823 });      // 写入M100  long值
                s7NetServer.Write("M100", new ulong[] { 1231231242312, 34312312323214, 9731283862312631823 });   // 写入M100  ulong值
    

    5. 高级读写,所谓的高级的读写,就是读写基础的字节数据,相关的转换需要自己来完成

    读数据的例子如下:

                OperateResult<byte[]> read = s7NetServer.Read("M100", 8);
                if (read.IsSuccess)
                {
                    float temp   = s7NetServer.ByteTransform.TransInt16(read.Content, 0) / 10f;
                    float press  = s7NetServer.ByteTransform.TransInt16(read.Content, 2) / 100f;
                    int count    = s7NetServer.ByteTransform.TransInt32(read.Content, 2);
    
                    // do something
                }
                else
                {
                    // failed
                }
    

    写数据的例子:

                // 拼凑数据,这样的话,一次通讯就完成数据的全部写入
                byte[] buffer = new byte[8];
                s7NetServer.ByteTransform.TransByte((short)1234).CopyTo(buffer, 0);
                s7NetServer.ByteTransform.TransByte((short)2100).CopyTo(buffer, 2);
                s7NetServer.ByteTransform.TransByte(12353423).CopyTo(buffer, 4);
    
                OperateResult write = s7NetServer.Write("M100", buffer);
                if (write.IsSuccess)
                {
                    // success
                }
                else
                {
                    // failed
                }
    
                // 上面的功能等同于三个数据分别写入,下面的方式性能稍微差一点点,几乎看不出来
                // s7NetServer.Write( "M100", (short)1234 );
                // s7NetServer.Write( "M100", (short)2100 );
                // s7NetServer.Write( "M100", 12353423 );
    

    6. 服务器的高级操作,日志配置

            public void S7Start2()
            {
                try
                {
                    s7NetServer = new SiemensS7Server();
                    s7NetServer.LogNet = new HslCommunication.LogNet.LogNetSingle("logs.txt");        // 配置日志信息
                    s7NetServer.ServerStart(102);
                }
                catch (Exception ex)
                {
                    Console.Write("Failed:" + HslCommunication.BasicFramework.SoftBasic.GetExceptionMessage(ex));
                }
            }
    

    7. 限制客户端的ip地址,下面举例是仅仅允许本机登录。

            public void S7Start3()
            {
                try
                {
                    s7NetServer = new SiemensS7Server();
                    s7NetServer.LogNet = new HslCommunication.LogNet.LogNetSingle("logs.txt");        // 配置日志信息
                    s7NetServer.SetTrustedIpAddress(new List<string>() { "127.0.0.1" });              // 仅仅限制本机客户端读写
                    s7NetServer.ServerStart(102);
                }
                catch (Exception ex)
                {
                    Console.Write("Failed:" + HslCommunication.BasicFramework.SoftBasic.GetExceptionMessage(ex));
                }
            }
    

    8. 捕捉数据接收事件,每当客户端进行数据交互的时候,都可以触发事件,然后可以对报文进行分析,比如说,分析出了客户端写入了地址M100的数据,就触发下自定义的操作,在这种情况下就可以使用如下的代码

            public void S7Start4()
            {
                try
                {
                    s7NetServer = new SiemensS7Server();
                    s7NetServer.LogNet = new HslCommunication.LogNet.LogNetSingle("logs.txt");        // 配置日志信息
                    s7NetServer.SetTrustedIpAddress(new List<string>() { "127.0.0.1" });              // 仅仅限制本机客户端读写
                    s7NetServer.OnDataReceived += S7NetServer_OnDataReceived;
                    s7NetServer.ServerStart(102);
                }
                catch (Exception ex)
                {
                    Console.Write("Failed:" + HslCommunication.BasicFramework.SoftBasic.GetExceptionMessage(ex));
                }
            }
    
            private void S7NetServer_OnDataReceived(object sender, byte[] data)
            {
                Console.WriteLine(HslCommunication.BasicFramework.SoftBasic.ByteToHexString(data, ' ')); // 打印客户端发送的数据
            }
    

    9. 示例,举个简单的例子,用来模拟PLC的程序,整个PLC的程序无非是对输入输出进行代码操作,PLC的优势就是实时性,所以我们可以基于本组件开发一个虚拟化的PLC,可用于简单的模拟,调试,测试操作。

  • 相关阅读:
    Two strings CodeForces
    Dasha and Photos CodeForces
    Largest Beautiful Number CodeForces
    Timetable CodeForces
    Financiers Game CodeForces
    AC日记——整理药名 openjudge 1.7 15
    AC日记——大小写字母互换 openjudge 1.7 14
    AC日记——将字符串中的小写字母换成大写字母 openjudge 1.7 13
    AC日记——加密的病历单 openjudge 1.7 12
    AC日记——潜伏着 openjudge 1.7 11
  • 原文地址:https://www.cnblogs.com/dathlin/p/10425797.html
Copyright © 2011-2022 走看看