1. 程式人生 > >C# 構建S7服務器 西門子的虛擬服務器 測試通訊 HslCommunication應用

C# 構建S7服務器 西門子的虛擬服務器 測試通訊 HslCommunication應用

amp per 數據 簡單 建議 label ted siem sharp

本文將使用一個gitHub開源的組件技術來實現S7服務器的功能,使用的是基於以太網的TCP/IP實現,不需要額外的組件

github地址:https://github.com/dathlin/HslCommunication 技術分享圖片 技術分享圖片 如果喜歡可以star或是fork,還可以打賞支持。

官網地址:http://www.hslcommunication.cn/ 打賞請認準官網

技術支持QQ群(主要面向工業軟件及HSL組件的):群1:592132877(滿) 群2:948305931 (組件的版本更新細節也將第一時間在群裏發布)最後編輯日期:2019年2月24日 12:14:10

裏面各種小夥伴,為您解答數據交互,編程技巧,如果對本界面提供的API有任何疑問,都可以加群咨詢,如果有更好的建議,歡迎提出。


演示的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,可用於簡單的模擬,調試,測試操作。

C# 構建S7服務器 西門子的虛擬服務器 測試通訊 HslCommunication應用