PYTHON工業互聯網監控項目實戰2—OPC
OPC(OLE for Process Control)定義:指爲了給工業控制系統應用程序之間的通信建立一個接口標準,在工業控制設備與控制軟件之間建立統一的數據存取規範。它給工業控制領域提供了一種標準數據訪問機制,將硬件與應用軟件有效地分離開來,是一套與廠商無關的軟件數據交換標準接口和規程,主要解決過程控制系統與其數據源的數據交換問題,可以在各個應用之間提供透明的數據訪問。實際項目中“設備”就變成一個可以訪問的OPC Server和它的Tag位號值,更多的詳情請參考OPC基金會官網:http://opcfoundation.cn/。
上一小節我們首先通過一個簡單的json格式來完成數據到UI端的傳輸,UI端解析Json數據,並通過JQuery渲染到div上來完成數據的顯示,最後ajax輪詢實現了數據的實時刷新。本小節我們把Domo進一步迭代改進,首先規範數據傳輸的格式,然後,實現實時讀取模擬OPC Server的tag位號值。
1.1. 界面UI與Json數據結構
採用面向對象的模式來定義數據傳輸Json格式,“設備”對象包含多個“tag”屬性值。上一小節例子中,我們從後臺獲取的數據格式是一個Json字符串,只定義了tank4C9的相關屬性。
tank4C9={
'Status': random.randint(0,1), #設備運行狀態
'OverheadFlow':random.randint(1,10) ,#'頂流量',
'ButtomsFlow': random.randint(1,10), #'低流量'
'Power': random.randint(10000,100000), #功率
}
實際項目中的監控界面會涉及到多個設備和多個監控tag位號,爲了便於數據的規範管理和更新,Json數據格式構造採用面向對象的模式進行構建如下:
tank4C9={
'DeviceId': 1,
'DeviceName':'1#反應罐',
'Status': random.randint(0,1), #設備運行狀態
'OverheadFlow':random.randint(1,10) ,#'頂流量',
'ButtomsFlow': random.randint(1,10), #'低流量'
'Power': random.randint(10000,100000), #功率
}
Json代碼就構建了一個圖例反應罐主要監控數據,注意多出來的設備狀態點,也就是用來體現設備是運行狀態還是停機狀態。另外,爲了體現這個設備來自那個一個OPC Server服務,更好地體現現場設備與採集器(OPC Server)的關係,再增加一層關於採集器的Json結構python代碼如下:
tank4C9={
'DeviceId': 1,
'DeviceName':'1#反應罐',
'Status': random.randint(0,1), #設備運行狀態
'OverheadFlow':random.randint(1,10) ,#'頂流量',
'ButtomsFlow': random.randint(1,10), #'低流量'
'Power': random.randint(10000,100000), #功率
}
Collector={
'CollectorId': 1,
'CollectorName':'1#採集器',
'Status': 0,
'DeviceList':[tank4C9],
}
從上述代碼的數據關係上,我們能看出來設備“1#反應罐”屬於“1#採集器”,數據採集器本身也有自己的設備運行狀態位號,來標識採集設備自身是否正常運行。
1.2. 重構Collector APP代碼
接下來我們重構Collector APP代碼,增加一個getCollectorData函數來返回連接器數據。
1.Collector APP views 增加函數getCollectorData代碼如下:
def getCollectorData(request):
tank4C9={
'DeviceId': 1,
'DeviceName':'1#反應罐',
'Status': random.randint(0,1), #設備運行狀態
'OverheadFlow':random.randint(1,10) ,#'頂流量',
'ButtomsFlow': random.randint(1,10), #'低流量'
'Power': random.randint(10000,100000), #功率
}
Collector={
'CollectorId': 1,
'CollectorName':'1#採集器',
'Status': 0,
'DeviceList':[tank4C9],
}
return HttpResponse( json.dumps(Collector));
2.修改項目urls文件urlpatterns ,發佈getCollectorData path
from django.urls import path
from Collector import views
urlpatterns = [
# Uncomment the next line to enable the admin:
#path('admin/', admin.site.urls)
path('getTank4C9Data/', views.getTank4C9Data),
path('getCollectorData/', views.getCollectorData),
]
項目調試狀態我們可以通過瀏覽器直接訪問url查看webAPI結果。http://127.0.0.1:8090/getCollectorData/
注意:Json數據格式的變化,圖中數據體現出了基於面向對象模式的層次結構“1#採集器”下面有一個包含的“設備對象列表”DeviceList屬性。
1.3. 修改UI代碼
現在修改tank4C9.html文件裏面的getData異步獲取數據函數代碼修改爲讀取上面getCollectorData函數如下:
//JQuery 代碼入口
$(document).ready(function(){
setInterval("getData()",1000);
});
function getData() {
//模擬異步從後臺獲得值
$.ajax({
url: "/getCollectorData/", success: function (result) {
data = JSON.parse(result);
tank4C9=data.DeviceList[0]
$("#OverheadFlow").html(tank4C9.OverheadFlow);
$("#ButtomsFlow").html(tank4C9.ButtomsFlow);
$("#Power").html(tank4C9.Power);
}});
}
</script>
調試運行http://127.0.0.1:8090/tank4C9/ UI同樣的實時自動刷新後臺數據的瀏覽效果。
重點:代碼重構的要點的功能不變的情況下,優化代碼結構。
代碼的結構優化,優先保證功能不變,儘量不要試圖在一次迭代中引入過多的變量,這樣只會導致編程工作雜亂無章的進行。Json格式代碼重構完成後,接下來我們把代碼調整成讀取OPC Server服務的Tag點。
1.4. 從OPC Server讀取Tag值
現在我們重構getCollectorData函數代碼,通過OPC服務讀取真正的設備值,當然dome的例子是讀取一個模擬OPC服務,實際項目中讀取設備發佈的OPC服務即可,代碼如下:
tank4C9={
'DeviceId': 1,
'DeviceName':'1#反應罐',
'Status': 0, #設備運行狀態
'OverheadFlow':0 ,#'頂流量',
'ButtomsFlow': 0, #'低流量'
'Power': 0, #功率
}
import OpenOPC
opc = OpenOPC.client()
opc.connect('Matrikon.OPC.Simulation')
tank4C9['OverheadFlow']= opc['Random.Int1']
tank4C9['ButtomsFlow']= opc['Random.Int2']
tank4C9['Power']= opc['Random.Int4']
opc.close()
Collector={
'CollectorId': 1,
'CollectorName':'1#採集器',
'Status': 0,
'DeviceList':[tank4C9],
}
return HttpResponse( json.dumps(Collector));
現在重新調試運行並瀏覽監控界面http://127.0.0.1:8090/tank4C9/動態效果如下:
1.5. 小結
本小節我們演示瞭如何在功能不變的模式下重構代碼來實現功能的迭代和推進,過程中始終貫穿功能不變的前提下重構代碼的結構來滿足新迭代功能的要求,然後再改變代碼功能讀取OPC服務tag位號值。最終調整了Json的數據封裝格式和實時設備數據從設備OPC Server中獲取,也演示了從技術探索原型到生產原型的代碼迭代過程。下一節我們將把ajax輪詢演進到通過websocket來實現UI端的數據刷新,提高數據刷新的效率。