Python industrial Internet monitoring project actual combat 3-websocket to UI

  This section continues to demonstrate how to use the early websocket technology prototype in the Django project to push the OPC server data to the UI in real time , and let the monitoring page display the process data of the field device in real time under another technical method. In this case, we still use the lightweight dwebsocket component.

1.  Install the dwebsocket component 

  Installation command: pip install dwebsocket  

1.1.  How to use dwebsocket 

  If you want to handle a websocket connection for a separate view, you can use the accept_websocket decorator, which will route standard HTTP requests to the view. Using the require_websocke decorator only allows WebSocket connections and will reject normal HTTP requests.  

  Add the setting MIDDLEWARE_CLASSES = dwebsocket.middleware.WebSocketMiddleware in the settings. This will reject the use of websocket for individual views, and you must add the accept_websocket decorator. 

   Setting WEBSOCKET_ACCEPT_ALL = True allows each individual view to use websockets

 1.2.  Common methods and properties

  1.request.is_websocket () If it is a websocket request returns True , if it is a normal http request returns False, you can use this method to distinguish them. 

  2.request.websocket   After a websocket request is established, this request will have a websocket attribute to provide a simple API communication to the client . If request.is_websocket () is False , this attribute will be None . 

  3. WebSocket.wait ()   returns a message sent by the client, he will not return any value before the client closes the connection, in this case, the method will return None 

  4.   If WebSocket.read () does not receive a new message from the client, the read method will return a new message, if not, it will not return. This is a non-blocking alternative to wait 

   5. WebSocket.count_messages () returns the number of message queues 

  6. WebSocket.has_messages ()   returns True if there are new messages , otherwise returns False 

  7. WebSocket.send (message) sends a message to the client 

  8. WebSocket .__ iter __ () websocket iterator 

  dwebsocket is relatively simple to use, adding a simple server url and refactoring the UI code; the UI code can create a websocket connection and process the returned data in the onmessage event, and you can quickly upgrade the monitoring page to no cost In a new way, let's look at the code evolution.

2. Refactor the server code - add a pushed websocket url

  Use accept_websocket decorated in Collector APP of views increases a file pushCollector way to achieve the UI server connected to the terminal, the server apparatus in real time using websocket active push UI interface to process data, the function code is as follows:

from dwebsocket.decorators import accept_websocket
import OpenOPC
@accept_websocket   
def pushCollectorData(request):

    tank4C9 = {            
         ' the DeviceId ' :. 1 ,
         ' DeviceName ' : ' . 1 # reaction tank ' ,
         ' the Status ' : 0, # equipment status 
        ' OverheadFlow ' : 0, # 'top flow', 
        ' ButtomsFlow ' : 0, # ' low flow ' 
        ' the power ' : 0, # power 
    }
    Collector = {
             ' CollectorId ' : 1 ,
             ' CollectorName ' : ' 1 # collector ' ,
             ' Status ' : 0,
             ' DeviceList ' : [tank4C9],
            } 
    Collector = {
          ' CollectorId ' : 1 ,
          ' CollectorName ' : ' 1 # collector ' ,
          ' Status ' : 0,
          ' DeviceList ' : [tank4C9],
         }  

    if request.is_websocket():
        try:
            while True:   

                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()
                request.websocket.send(\
                    json.dumps( {"rows":[Collector],'total':1}))
                time.sleep(2)
 
        finally:
            client.disconnect()

  Interpretation: The main difference between the above code and the original is that the tag value of the opc service is read from the passive refresh (after the UI request), and it becomes the interval time.sleep (2) seconds. UI side.

3.  Refactor UI code

   Here django and Flask difference is no need to create a new project, the current project we can by reconstructing use websocket real-time push function tank4C9.html page code.

  The reconstructed tank4C9.html code is as follows: 

<html>
<head><title></title>
    <script src="https://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
    </head>

<body>

    <div>
        Status:    <strong id="divStatus">0</strong>
    </div>
    <div>
        OverheadFlow:    <strong id="divOverheadFlow">0</strong>
    </div>
    <div>
        ButtomsFlow:    <strong id="divButtomsFlow">0</strong>
    </div>
    <div>
        Power:    <strong id="divPower">0</strong>
    </div>


    <div>
        pushCount:    <strong id="divpushCount">0</strong>
    </div>


    < script > 
        // JQuery code entry 
        $ (document) .ready ( function () {
 

            if ("WebSocket" in window) {
                //连接server--TagCurValue
                var ws = new WebSocket("ws://127.0.0.1:8090/pushCollector/");
                ws.onmessage =  function (evt) {
                     // Receive data 
                    d = JSON.parse (evt.data);
                    collector= d.rows[0]
                    for (i = 0; i < collector.DeviceList.length; i++){
                        device = collector.DeviceList[i]
                        $("#divStatus").html(device.Status);
                        $("#divOverheadFlow").html(device.OverheadFlow);
                        $("#divButtomsFlow").html(device.ButtomsFlow);
                        $("#divPower").html(device.Power);
                        $("#divpushCount").html(device.Count);

                    }                   

                };
            } 
        });

    </script>

</body>
</html>

   Interpretation: The UI side code updates the page display through the ws.onmessage event. Compared with the previous ajax polling mode code, the main structure and function of the code have not changed significantly, but a new data transmission method has been adopted. .

  Note : 

  var ws = new WebSocket("ws://127.0.0.1:8090/pushCollector/");

  The last " /" in pushCollector / url , this point is a difference between django and flask , otherwise we will receive a 301 error message when creating this websocket ! 

4. Publish pushCollectorData url

  The urls of the project publish this new url interface address, in this case we retain the original getCollectorData, the code is as follows: 

# Uncomment next two lines to enable admin:
#from django.contrib import admin

from django.urls import path
from Collector import views

urlpatterns = [
    # Uncomment the next line to enable the admin:
    #path('admin/', admin.site.urls)

    path('tank4C9/', views.tank4C9),
    path('getCollectorData/', views.getCollectorData),
    path('pushCollectorData/', views.pushCollectorData),
    
]

4. commissioning run results

5.  Summary

  In this section, we completed the technical architecture iteration of the real-time monitoring screen from the background server to the UI through the active push of websocket. In this process, we also demonstrated the project iteration method. The benefits of iteratively advancing the project function points are very obvious. On the premise that one version meets the demand, it is relatively easy to adopt new technologies and solutions to upgrade products and improve performance.

  For example, we retain the original getCollectorData url. The actual project development is also organized by adding a new push method, so that the new upgrade also meets the background access method of the original ajax mode. In order to avoid the inconsistency of the original page during the upgrade process, the original page cannot be accessed normally, and the "disaster" problem of "crash" after the system has been released.

  Let ’s talk more about the “small step, fast iteration” mode under agile programming. The problem encountered by some teams is that the minimalist design meets the current requirements at the beginning, and then the project product architecture technology rapidly ages during the continuous function iteration process. However, the team continues to increase the number of functional points, and no one cares about the optimization and adjustment of the technical architecture. In the end, the problems accumulate more and more, the architecture becomes more difficult to use, the product builds more and more slowly, and finally wait for a complete project "refactoring". Some "good" projects should gradually evolve the code structure in the process to meet the expanding functional requirements.

  The premise of agile programming is to have a system to ensure it, requirements management, code refactoring, unit testing, etc. For example: code refactoring is very important in the process of agile programming projects. It is easy to meet the needs at the beginning. When the new requirements code can not meet the changes of the requirements well, introduce good design patterns, optimize the code structure by means of code refactoring, and use regression unit testing to ensure that the new code structure can pass the original unit tests normally. Blindly adopting agile programming without adopting a set of mechanisms for its effective management, and finally caught in the quagmire of the project, can only be said that the core elements of "agile" are not well understood.

 

Guess you like

Origin www.cnblogs.com/haozi0804/p/12725449.html