1. 程式人生 > >python工業網際網路監控專案實戰2—OPC

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函式如下: 

   <script>

       //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服務即可,程式碼如下: 

 <script>
def getCollectorData(request):

    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端的資料重新整理,提高資料重新整理的效率。

&n