websocket實時監控畫面


  Ajax輪詢是通過特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,然后由服務器返回最新的數據給客戶端的瀏覽器。這種簡單粗暴模式有一個明顯的缺點,就是瀏覽器需要不斷的向服務器發出請求,HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費很多的帶寬等資源(對於很多局域網內的企業應用,這個簡單粗暴模式確實解決問題)。

1.1.    websocket簡介

  本文接下來采用一種更加高效率的服務端主動推送技術(WebSocket )來提高數據的傳輸效率。WebSocket通信協議 是 HTML5 開始支持的一種在單個 TCP 連接上進行全雙工通訊的協議。在 WebSocket 技術架構中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。

  瀏覽器通過 JavaScript 向服務器發出建立 WebSocket 連接的請求,連接建立以后,客戶端和服務器端就可以通過 TCP 連接直接交換數據。當你獲取 Web Socket 連接后,可以通過 send() 方法來向服務器發送數據,並通過 onmessage 事件來接收服務器返回的數據。  

1.2.  創建一個Flask-Sockets服務端項目

  本例我們通過VS2019創建一個空的Python項目,來實現Flask-Sockets服務端代碼,我們在現有的解決方案里添加一個Project,如下圖:

 

1.2.1. 安裝Flask-Sockets組件

Flask我們可采用Flask-Sockets組件來實現websocket 通信驗證原型,

組件網址:https://github.com/heroku-python/flask-sockets

安裝命令:pip install Flask-Sockets

vs community 我們可以直接在Python Environment 安裝Flask-Sockets組件(注意字母大小寫,否則不能安裝成功),如下圖:

1.2.2. 實現websocket服務端源碼

服務端先實現由服務端定時推送一個自增的變量值給客戶端,代碼如下:

      
from flask import Flask
from flask_sockets import Sockets
import time

app = Flask(__name__)
sockets = Sockets(app)


@sockets.route('/tagCurValue')
def tagCurValue(ws):
    '''
        代碼模擬每5秒鍾,定時給客戶端推送一個自增的變量數據
    '''
    n=0
    while not ws.closed:
        n=n+1
        ws.send(str(n))
        print("tag curent value:"+ str(n))
        time.sleep(5)


@app.route('/')
def hello():
    return 'Hello World!'


if __name__ == "__main__":
    from gevent import pywsgi
    from geventwebsocket.handler import WebSocketHandler
    server = pywsgi.WSGIServer(('0.0.0.0', 5000), application=app, handler_class=WebSocketHandler)
    print('Server Start')
    server.serve_forever()  

server = pywsgi.WSGIServer(('0.0.0.0', 5000), application=app, handler_class=WebSocketHandler)

上述代碼的'0.0.0.0'要注意賦值,組件的Example例子是一個空字符串,筆者也踩了坑,花費不少時間才找到案例運行失敗的原因。

1.2.3. 運行FlaskSocketSvr服務端

首先,我們需要把FlaskSocketSvr設置成解決方案的默認項目,后然F5運行測試環境如下圖:

瀏覽器地址欄輸入以下網址:http://127.0.0.1:5000/ 結果如下圖:

 

1.2.4. 重構客戶端代碼

  現在我們重構客戶端代碼以便可以訪問服務端提高的websocket URL獲得數據更新

http://127.0.0.1:5000/tagCurValue 

UI JS代碼如下:

        //JQuery 代碼入口
        $(document).ready(function(){
 
            //setInterval("getData()",3000);

            if ("WebSocket" in window) {
                //連接server--TagCurValue
                var ws = new WebSocket("ws://127.0.0.1:5000/tagCurValue");
                //var ws = new WebSocket("ws://127.0.0.1:8008/tagCurValue");
                ws.onmessage = function (evt) {
                    // 接收數據
                    receivedMsg = evt.data;
                    $("#divTag").html(receivedMsg);

                };
            }

 
        });

  

現在我們在Project通過Python菜單執行Start server,然后再F5運行服務端,我們就可以通過瀏覽器運行測試頁面了。

 

測試頁面url:http://127.0.0.1:8008/

 

我們也能通過瀏覽器的開發工具查看網絡訪問只發生了一次。

 

1.3.    讀取opc服務的tag位號值

  最后,我們再把tagCurValue'重構成真正讀取opc服務某一個tag位號的值。以完成了從UI端到服務端主動獲取opc服務tag位號值,並更新UI界面的技術原型。views文件函數tagCurValue'代碼修改如下:

@sockets.route('/tagCurValue')
def tagCurValue(ws):
    import OpenOPC
    while not ws.closed:
        opc = OpenOPC.client()
        opc.connect('Matrikon.OPC.Simulation')
        result= opc['Random.Int1']
        opc.close()
        ws.send(unicode( result))
        print("tag curent value:"+ unicode( result))
        time.sleep(5)

 現在,我們重新運行測試環境,結果如下圖:

1.4.    小結

  本小節介紹了如何通過采用websocket技術,實現由服務端主動Send數據到UI端的通信模式,客戶端實時刷新UI端tag位號的當前值,提高了數據傳輸的效率和性能,樣例的FlaskSocketSvr服務也演示了一個獨立的服務端到UI端的數據傳輸方式(獨立的服務端地址)。最后,新的服務也通過讀取OPC server的tag位號值演示了通過OPC Sever獲取監控設備數據的方式。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM