本文介紹在一些特殊的場景和需求下,使用HslCommunication的可以實現一些比較有意思的功能。例行介紹HSL的安裝
github地址:https://github.com/dathlin/HslCommunication 如果喜歡可以star或是fork,還可以打賞支持,打賞請認准源代碼項目。
聯系作者及加群方式:http://www.hslcommunication.cn/
在Visual Studio 中的NuGet管理器中可以下載安裝,也可以直接在NuGet控制台輸入下面的指令安裝:
Install-Package HslCommunication
如果需要教程:Nuget安裝教程:http://www.cnblogs.com/dathlin/p/7705014.html
組件的完整信息和API介紹參照: http://api.hslcommunication.cn 組件的使用限制,更新日志,都在該頁面里面。
我們來看看這種系統的架構設計模式。
我們有一個主的后台服務器來連接現場的各種PLC設備,然后進行數據交互。這個沒有問題,很好實現,但是現在有需求,我們在遠程客戶端界面,或是手機端界面,瀏覽器界面,等等,需要對遠程的PLC進行讀寫一些數據操作,這時候怎么實現是最簡單方便的?
在HSL里,提供了兩種簡單的可能性。可以輔助你快速實現需要的操作信息。
1. 基於MRPC實現,詳細見文章:https://www.cnblogs.com/dathlin/p/14094128.html
優點:對客戶端的控制更強,權限控制也更加強,可以細化到每個API的權限控制,和MQTT深度結合,支持訪問TOPIC信息,傳輸數據有進度報告。
缺點:MRPC為定制協議,需要定制開發,目前實現了C#,java,python版本,其他平台或是語言都需要定制實現。
2.基於WebApi實現,下文詳細說明。
優點:客戶端標准化,使用postman即可測試,絕大多數語言和平台都支持webapi接口,已經有相關的輪子,可以直接調用。
缺點:MRPC的優點就是缺點。
我們開始寫代碼,我們先假設有1個PLC需要不停的采集,分析數據,做處理。我們新建一個控制台程序,安裝HslCommunication組件。為了方便起見,我們假設這個PLC是西門子PLC,實際上無論什么牌子的都是一樣的。
namespace ConsoleServer { class Program { static void Main( string[] args ) { SiemensS7Net plc = new SiemensS7Net( SiemensPLCS.S1200, "127.0.0.1" ); // 此處拿了本地虛擬的PLC測試 plc.SetPersistentConnection( ); // 設置了長連接 while (true) { Thread.Sleep( 1000 ); // 每秒讀取一次 OperateResult<short> read = plc.ReadInt16( "M100" ); if (read.IsSuccess) { // 讀取成功后,進行業務處理,存入數據庫,或是其他的分析 Console.WriteLine( "讀取成功,M100:" + read.Content ); } else { // 讀取失敗之后,顯示下狀態 Console.WriteLine( "讀取PLC失敗,原因:" + read.Message ); } } } } }
此處就簡化了一些操作信息,反正是要執行一些業務操作的。現在我們需要在客戶端的程序里,增加一個按鈕,比如功能是鎖定機台。這個功能的實現是寫入M300.1為True。如果解鎖,就是寫false
因為我們的客戶端是部署在其他電腦的,當然是需要新建一個winform的項目了,如果是WPF也是一樣的。也是弄兩個按鈕出來,然后寫事件。
有了事件之后,我們怎么來寫代碼呢?
如果想實現基於webapi來讀寫,代碼非常精簡。我們改造下服務器端的實現:
namespace ConsoleServer { class Program { static void Main( string[] args ) { SiemensS7Net plc = new SiemensS7Net( SiemensPLCS.S1200, "127.0.0.1" ); // 此處拿了本地虛擬的PLC測試 plc.SetPersistentConnection( ); // 設置了長連接 HttpServer httpServer = new HttpServer( ); httpServer.RegisterHttpRpcApi( "MainPlc", plc ); httpServer.Start( 8000 ); // 需要管理員啟動 while (true) { Thread.Sleep( 1000 ); // 每秒讀取一次 OperateResult<short> read = plc.ReadInt16( "M100" ); if (read.IsSuccess) { // 讀取成功后,進行業務處理,存入數據庫,或是其他的分析 Console.WriteLine( "讀取成功,M100:" + read.Content ); } else { // 讀取失敗之后,顯示下狀態 Console.WriteLine( "讀取PLC失敗,原因:" + read.Message ); } } } } }
增加了三段話,實例化服務,注冊PLC,啟動。
當前的服務器提供了什么RPC的接口呢?,我們運行起來。然后用HslCommunication的DEMO程序打開瞧瞧就可以了。
服務器端啟動之后,就是一直在打印讀取成功了。沒有其他的內容
好了,到這里我們的程序寫完了,我們的PLC已經提供了遠程讀寫的WebApi的接口了,可能我們會問,在哪里呢?我們打開demo看看。
上面的操作之后我們看到了所有的接口列表。
我們點擊其中的一個接口,例如 ReadOrderNumber 接口,我們想讀取PLC的訂貨號。點擊之后,界面變化了。
不管他,我們直接點擊讀取。
我們看到有數據返回了。我們成功讀取到了一個json字符串,是不是很熟悉,獲取規則如下:
因為讀取是可能會失敗的,也就是Content屬性可能為空,那么我們就需要先判斷 IsSuccess 為 True ,我們再去拿Content的數據。
如果為 False, 那么代表讀取失敗了,失敗原因就在 Message 里面。這時候,你可以顯示出來。或是記錄日志,寫入寫入數據庫都是可以的。
我們再來嘗試讀取M100的short數據,在PLC里就是 MW100的值。
結果如下:
當我們重新選擇ReadInt16接口的方法時,
這時候已經顯示當前的接口已經有一次調用的信息了。
我們再測試一個寫入的操作。
我們可以讀取驗證一下、
OK,我們現在用POSTMAIN測試一下。
需要注意的是,當前的方法是POST的。
既然支持webapi,最后我們來嘗試在網頁上的操作,我們先做一個網頁,放一個按鈕,然后搞一個點擊事件。去請求數據,然后顯示讀取結果。我們用到了 jquery,頁面如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>HslCommunication教程</title> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> </head> <body> <h1>測試Webapi的內容</h1> <p>點擊下方的按鈕即可 </p> <button onclick="GetPlcValue()">測試</button> <p>結果如下:</p> <p id="test1"></p> <script type="text/javascript"> function GetPlcValue(){ $.ajax({ type:'post', async: false, url:'http://127.0.0.1:8000/MainPlc/ReadInt16', dataType:'JSON', data:JSON.stringify({ 'address': 'M100' }), success:function(result){ console.log(result); if(result.IsSuccess){ $("#test1").text("Read Success, value is : " + result.Content); } else{ $("#test1").text("Read Failed, Message: " + result.Message); } } }); } </script> </body> </html>
很簡單沒啥內容,我們運行下。
emmm,好像遇到跨域問題了,沒關系,我們在服務器上稍微更改一下。
然后我們在頁面上再次進行操作一下:
同理,寫入都是類似的。
最后我們來聊聊,如何實現你自己的API接口到 webapi上。例如我們要增加一個算法的接口,傳入兩個數,返回方法之和。
我們定義一個類。
public class Algorithms { [HslCommunication.Reflection.HslMqttApi(HttpMethod = "POST", Description = "這是一個計算兩個數相加的方法。")] public int Add(int a, int b ) { return a + b; } }
我們看這個方法,定義了POST,當然了,GET也可以的,這樣客戶端的方式只要匹配就好了。
然后我們注冊下服務
完事,我們看看客戶端的界面。
我們更改下傳入的值
當然,HttpServer進行用戶名驗證也是可以的。具體可以查看另一篇博客:https://www.cnblogs.com/dathlin/p/12335933.html
這時候的POSTMAN就是要攜帶基本的驗證了,我們來看看加一個權限控制的api的使用方法
public class Algorithms { [HslCommunication.Reflection.HslMqttApi(HttpMethod = "POST", Description = "這是一個計算兩個數相加的方法。")] public int Add(int a, int b ) { return a + b; } [HslCommunication.Reflection.HslMqttPermission(UserName = "admin")] [HslCommunication.Reflection.HslMqttApi( HttpMethod = "POST", Description = "這是一個計算兩個數相乘的方法。" )] public int Multipy( int a = 10, int b = 20 ) { // 當前方法只能用戶名為admin的調用 return a * b; } }
我們增加的第二個方法就是增加權限的控制,這樣的話,客戶端再請求的話,就是需要增加權限頭
我們先看POSTMAN
我們看到了返回了數據,然后我們再看看發送的header里都有什么
這個內容就校驗的內容之一了,好了,我們在js里可以這么寫代碼了
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>HslCommunication教程</title> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> </head> <body> <h1>測試Webapi的內容</h1> <p>點擊下方的按鈕即可 </p> <button onclick="GetPlcValue()">測試</button> <p>結果如下:</p> <p id="test1"></p> <script type="text/javascript"> function GetPlcValue(){ $.ajax({ headers:{ 'Authorization': 'Basic YWRtaW46MTIzNDU2' }, type:'post', async: false, url:'http://127.0.0.1:8000/Algorithms/Multipy', dataType:'JSON', data:JSON.stringify({ 'a': 10, 'b': 20 }), success:function(result){ console.log(result); $("#test1").text("Read Success, value is : " + result); //if(result.IsSuccess){ //$("#test1").text("Read Success, value is : " + result.Content); //} //else{ //$("#test1").text("Read Failed, Message: " + result.Message); //} } }); } </script> </body> </html>
然后再運行,就是返回了正確的結果了
如果有什么其他的問題,歡迎留言。