本文將使用一個gitHub開源的組件技術來實現S7服務器的功能,使用的是基於以太網的TCP/IP實現,不須要額外的組件css
github地址:https://github.com/dathlin/HslCommunication
若是喜歡能夠star或是fork,還能夠打賞支持。git
官網地址:http://www.hslcommunication.cn/ 打賞請認準官網github
演示的demo,快速開發,下載demo程序,您能夠進行初步的訪問的測試,免去了您寫測試程序的麻煩,快速實驗通信,測試開發軟件的操做。數組
下載地址爲:HslCommunicationDemo.zip 服務器
演示的服務器截圖爲:性能
再配合本組件支持的客戶端通信、就能夠實現自我測試。測試
二者的地址格式是一致的。大數據
服務器端支持4種地址:輸入的I0,輸出的Q0,中間寄存器M100,DB塊,DB1.100ui
實際的場景中,頗有可能你須要的是一個能夠測試的demo,當你在開發上位機,SCADA軟件,監控軟件,歷史追述軟件的時候,尚未PLC來給你測試,開發,這時候就可使用本demo來實現模擬服務器的功能。spa
固然還有另外一種需求,當你要集成一個服務器到你本身的程序中的時候,就可使用本組件來實現,而要集成一個自定義的服務器將會是很是的簡單。
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,可用於簡單的模擬,調試,測試操做。