python工業互聯網監控項目實戰5—Collector到opcua服務
本小節演示項目是如何從連接器到獲取Tank4C9服務上的設備對象的值,並通過Connector服務的url返回給UI端請求的。另外,實際項目中考慮websocket中間可能因為網路通訊等原因出現中斷情況,我們增加一個「心跳」設計來定時發送連接請求,確保出現沖斷的情況下,能夠重新連接到服務端。
1. OPCUA-Client讀取OPCUA服務Tag值
現在重構Connector APP views文件里的pushCollectorData函數,通過引入OPCUA-Client來讀取OPCUA服務端的Tag值,程式碼如下:
from django.shortcuts import render from django.http import HttpResponse import json from dwebsocket.decorators import accept_websocket from opcua import Client #引入 opcua-client @accept_websocket def pushCollectorData(request): tank4C9={ 'DeviceId': 1, 'DeviceName':'1#反應罐', 'Status': 0, #設備運行狀態 'OverheadFlow':0 ,#'頂流量', 'ButtomsFlow': 0, #'低流量' 'Power': 0, #功率 } Collector={ 'CollectorId': 1, 'CollectorName':'1#採集器', 'Status': 0, 'DeviceList':[tank4C9], } Collector={ 'CollectorId': 1, 'CollectorName':'1#採集器', 'Status': 0, 'DeviceList':[tank4C9], } if request.is_websocket(): #創建opcua-client client = Client("opc.tcp://localhost:4840/freeopcua/server/") client.connect() #連接伺服器 try: while True: root = client.get_root_node() #獲取OPCUA服務根節點 #獲取Tank4C9子節點的所有變數 items = root.get_child(["0:Objects", "2:Tank4C9"]).get_children() for item in items: #給字典賦讀取opcua服務tag當前值 tank4C9[item.get_display_name().Text]=item.get_value() request.websocket.send(\ json.dumps( {"rows":[Collector],'total':1})) time.sleep(2) finally: client.disconnect()
程式碼改動並不大,數據獲取從原來的OPC DA切換到了OPC UA組件,從前面的章節起筆者就奉行迭代推進的思路,好的程式碼結構(組織)會讓後面的升級重構非常的方便,實際項目中減少很多工作量。
2. 運行調試
首先,我們在集成開發環境VS Community 2019 選擇CollectorSvr項目,右鍵在python環境啟動運行CollectorSvr項目,如下圖:
然後,F5調試默認服務端項目Tank4C9Svr。我們即可通過瀏覽器訪問監控頁面
url://127.0.0.1:8090/tank4C9/ 運行效果如下圖:
3. 客戶端心跳機制
本章節我們在UI端增加一個與服務端心跳檢測函數,當websocket網路通訊故障或其它原因不能正常傳輸數據時,UI端能夠重新創建連接來確保系統可靠性的手段。UI端保存一個最後更新時間的變數,心跳檢測時查看當前時間–最後更新時間大於30秒時,就關閉當前連接重新創建一個新得websocket連接獲取數據,這樣就確保了websocket出現其它原因斷開後,保證能夠自動重新連接並刷新數據得機制。
更多得看程式碼吧如下
<script> //JQuery 程式碼入口 $(document).ready(function () { getData() //設置心跳檢測時間 setInterval("heartbeat(window.ws,window.lastUpdateTime)",30000); }); function heartbeat(ws,lastUpdateTime) { var time = new Date(); if ((time.getTime() - lastUpdateTime > 30000)) { //最後更新時間與當前檢查時間大於30秒,關閉連接重新創建並獲取數據 if(ws) ws.close();//關閉連接 getData(); } } function getData() { if ("WebSocket" in window) { //連接server--TagCurValue window.ws = new WebSocket("ws://127.0.0.1:8090/pushCollectorData/"); window.lastUpdateTime = new Date().getTime() ws.onmessage = function (evt) { //最後更新時間戳 lastUpdateTime = new Date().getTime() // 接收數據 d = JSON.parse(evt.data); collector = d.rows[0] tank4C9 = collector.DeviceList[0] $("#OverheadFlow").html(tank4C9.OverheadFlow); $("#ButtomsFlow").html(tank4C9.ButtomsFlow); $("#Power").html(tank4C9.Power); }; } } </script>
4. 小結
本章節程式碼的改動不大,一個改動是切換到了OPC UA,另一個是增加了心跳檢測函數,這個兩個看似不大的改動,尤其心跳函數在實際項目中作用非常大,工業監控畫面,如果出現長時間的數據不刷新(僅僅是插拔了一下電腦網線)畫面不能自動連接到服務端刷新數據,現場管理員就看不到數據的變化,畫面就不能真實的反應設備運行情況,這個在實際項目中是不能被客戶接受的。OPC UA 的升級讓體系可以逐步演進到新的架構下,卻不會導致客戶端任何調整,這個就是好的分層架構的優勢,早些年筆者經歷的很多項目都是從後台改到前台,並測試發布才能更新功能。
5.後記
python開發工業監控系列文章到本章節就告以段落了,這個系列帶著大家從技術原型的探索到項目實戰,從一個簡單監控頁面開始一步一步的也演示了項目迭代的實際過程,筆者的項目最佳實踐準則:敏捷開發,有一個基本的功能藍圖後,從簡設計、開發、迭代、重構、單元測試、集成測試和發布等環環相扣。同時,採用一個好的可繁可簡的技術體系對持續改進非常重要,筆者轉換python體系以來,越發喜歡上開源社區,互聯網開發架構也會給傳統企業軟體開發領域帶來新的機遇,尤其國家大力推進的工業互聯網時代,期待python開發生態會帶給我們更多的驚喜。
這裡的案例UI比較簡單,實際的項目可能還會設計APP UI,或者更發雜的web 3D介面等,但是總體來說服務端的架構思路是不變的,開發設計的分層(邏輯分層)是好的技術架構的重要體現。本序列文章我們更多的著重在監控介面上,沒有交代業務邏輯和模型層面的知識,下一個系列筆者計劃更多的著重在業務邏輯和模型層。