本小节继续演示如何在Django项目中采用早期websocket技术原型来实现把OPC服务端数据实时推送到UI端,让监控页面在另一种技术方式下,实时显示现场设备的工艺数据变化情况。本例我们仍然采用比较轻量级的dwebsocket组件。

1. 安装dwebsocket组件

  安装命令:pip install dwebsocket  

1.1. dwebsocket使用方法

  如果你想为一个单独的视图处理一个websocket连接可以使用accept_websocket装饰器,它会将标准的HTTP请求路由到视图中。使用require_websocke装饰器只允许使用WebSocket连接,会拒绝正常的HTTP请求。

  在设置中添加设置MIDDLEWARE_CLASSES=dwebsocket.middleware.WebSocketMiddleware这样会拒绝单独的视图使用websocket,必须加上accept_websocket 装饰器。

  设置WEBSOCKET_ACCEPT_ALL=True可以允许每一个单独的视图实用websockets

1.2. 常用方法和属性

  1.request.is_websocket()  如果是个websocket请求返回True,如果是个普通的http请求返回False,可以用这个方法区分它们。

  2.request.websocket  在一个websocket请求建立之后,这个请求将会有一个websocket属性,用来给客户端提供一个简单的api通讯,如果request.is_websocket()是False,这个属性将是None。

  3.WebSocket.wait()  返回一个客户端发送的信息,在客户端关闭连接之前他不会返回任何值,这种情况下,方法将返回None

  4.WebSocket.read()  如果没有从客户端接收到新的消息,read方法会返回一个新的消息,如果没有,就不返回。这是一个替代wait的非阻塞方法

  5.WebSocket.count_messages()  返回消息队列数量

  6.WebSocket.has_messages()  如果有新消息返回True,否则返回False

  7.WebSocket.send(message)  向客户端发送消息

  8.WebSocket.__iter__()  websocket迭代器

  dwebsocket使用起来比较简单,增加一个简单的服务端url和重构UI代码;UI代码创建一个websocket连接并在onmessage 事件里处理返回的数据即可,不用花费多大的代价就能快速让监控页面升级到一个新的方式下,下面看代码演进吧。

2.重构服务端代码——增加一个推送的websocket url

  使用accept_websocket装饰器在Collector APP的views文件中增加一个pushCollector的方法,实现UI端连接上服务端后,服务端使用websocket主动向UI界面推送实时设备工艺数据,函数代码如下:

from dwebsocket.decorators import accept_websocket
import OpenOPC
@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():
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()

  解读:上文代码与原来的主要差别就是从被动刷新(UI请求后)读去opc服务的tag位号值,变成间隔time.sleep(2)秒读取数据后通过request.websocket.send到UI端。

3. 重构UI端代码

  这里django与Flask的差别就是无须新建一个新的项目,当前项目我们就可以通过重构tank4C9.html页面代码来使用websocket实时推送功能。

  重构后tank4C9.html代码如下:

<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 代码入口
$(document).ready(function(){ if ("WebSocket" in window) {
//连接server--TagCurValue
var ws = new WebSocket("ws://127.0.0.1:8090/pushCollector/");
ws.onmessage = function (evt) {
// 接收数据
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>

  解读:UI端代码通过ws.onmessage事件更新页面显示,对照上一张的ajax轮询模式的代码,代码的主体结构和功能并没有大的变化,只是采用了一种的新的数据传递方式而已。

  注意

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

  pushCollector/ url最后那个“/”,这个点是django与flask的一个差别,否则我们创建这个websocket时会收到301错误提示!

4. 发布pushCollectorData url

  项目的urls发布这新的url接口地址,这例我们保留原来的getCollectorData,代码如下:

# 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. 调试运行效果

5. 小结

  本小节我们通过websocket的主动推送方式,完成了实时监控画面从后台服务端主动推送到UI端的技术架构迭代,这个过程我们也演示了项目迭代的方式,迭代推进项目功能点的好处非常明显也就是在一个版本满足需求的前提下,可以相对从容的采用新的技术和方案升级产品改进性能。

  例子我们保留了原来的getCollectorData url,实际的项目开发也是通过增加新推送方法的方式来组织进行的,这样新的升级也同时满足原有ajax模式的后台访问方式。从而避免升级过程中,前后台升级版本不一致导致原有页面不能正常访问,避免系统已发布就“崩溃”的“灾难”问题。

  这里多说一下敏捷编程下的“小步快跑,快速迭代”模式下,一些团队遇到的问题就是一开始极简设计满足当下要求,然后在不断功能迭代过程中项目产品架构技术快速老化,可是团队还是不断的增加功能点,而没有人员关心技术架构优化和调整。最终,导致问题越积越多,架构越来越难用,产品构建越来越慢,最后等待一次彻底的项目“重构”。一些“好的”项目应该在过程中逐步演化代码结构来满足不断扩张的功能需求。

  敏捷编程的前提是要有一套体系来做保证的,需求管理、代码重构、单元测试等等,比如:代码重构在敏捷编程项目过程中就非常重要,一开始简单满足需求,一旦发现引入新的需求代码不能很好的满足需求的变化时,引入好的设计模式,采用代码重构的方式来优化代码结构,并通过回归单元测试来保证新的代码结构能够正常通过原来的单元测试。盲目的采用敏捷编程又没有采用它有效管理的一整套机制,最后陷入项目泥潭的,只能说是没有理解好“敏捷”的核心要素罢了。

Python工业互联网监控项目实战3—websocket to UI的更多相关文章

  1. python工业互联网监控项目实战5—Collector到opcua服务

    本小节演示项目是如何从连接器到获取Tank4C9服务上的设备对象的值,并通过Connector服务的url返回给UI端请求的.另外,实际项目中考虑websocket中间可能因为网络通信等原因出现中断情 ...

  2. python工业互联网监控项目实战2—OPC

    OPC(OLE for Process Control)定义:指为了给工业控制系统应用程序之间的通信建立一个接口标准,在工业控制设备与控制软件之间建立统一的数据存取规范.它给工业控制领域提供了一种标准 ...

  3. python工业互联网监控项目实战4—python opcua

    前面章节我们采用OPC作为设备到上位的信息交互的协议,本章我们介绍跨平台的OPC UA.OPC作为早期的工业通信规范,是基于COM/DCOM的技术实现的,用于设备和软件之间交换数据,最初,OPC标准仅 ...

  4. Python爬虫开发与项目实战

    Python爬虫开发与项目实战(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1MFexF6S4No_FtC5U2GCKqQ 提取码:gtz1 复制这段内容后打开百度 ...

  5. Python爬虫开发与项目实战pdf电子书|网盘链接带提取码直接提取|

    Python爬虫开发与项目实战从基本的爬虫原理开始讲解,通过介绍Pthyon编程语言与HTML基础知识引领读者入门,之后根据当前风起云涌的云计算.大数据热潮,重点讲述了云计算的相关内容及其在爬虫中的应 ...

  6. python工业互联网应用实战2—从需求开始

    前言:随着国家工业2025战略的推进,工业互联网发展将会提速,将迎来一个新的发展时期,越来越多的企业开始逐步的把产线自动化,去年年底投产的小米亦庄的智能工厂就是一个热议的新闻.小米/华为智能工厂只能说 ...

  7. python工业互联网应用实战3—模型层构建

    本章开始我们正式进入到实战项目开发过程,如何从需求分析获得的实体数据转到模型设计中来,变成Django项目中得模型层.当然,第一步还是在VS2019 IDE环境重创建一个工程项目,本文我们把工程名称命 ...

  8. python工业互联网应用实战1—SQL与ORM

    从sql到ORM应该说也是编程体系逐步演化的结果,通过类和对象更好的组织开个过程中遇到的各种业务问题,面向对象的解耦和内聚作为一套有效的方法论,对于复杂的企业应用而言确实能够解决实践过程中很多问题. ...

  9. python工业互联网应用实战18—前后端分离模式之jquery vs vue

    前面我们分三章来说明了使用django template与jquery的差别,通过jquery如何来实现前后端的分离,同时再9章节使用vue.js 我们浅尝辄止的介绍了JQuery到vue的切换,由于 ...

随机推荐

  1. Cisco 模拟配置

    本次模拟:采用Cisco Packet Tracer 软件,进行cisco网络设备的模拟.可以实现CLI界面命令配置,同实际交换机一样. 1.同一VLAN 可以互相访问,不同VLAN 不能访问 PC0 ...

  2. 图解kubernetes控制器StatefulSet核心实现原理

    StatefulSet是k8s中有状态应用管理的标准实现,今天就一起来了解下其背后设计的场景与原理,从而了解其适用范围与场景 1. 基础概念 首先介绍有状态应用里面的需要考虑的一些基础的事情,然后在下 ...

  3. OpenLDAP 多主复制(基于docker容器模式部署)

    **本文主要讲述在docker环境下如何进行 OpenLDAP 多主复制,至于 OpenLDAP 原理可以先参考这篇文章了解:https://cloud.tencent.com/developer/a ...

  4. Log4Net读取XML配置文件及在代码中完成添加Logger操作

    解决问题: 将log4net配置文件与app.config配置文件分开 手动读取log4net配置文件 手动创建logger 可将日志输出功能封装在类库中,应用程序引用时无需添加assembly引用及 ...

  5. java,jq,ajax写分页

    1.先写好html基础样式 我懒得去写css样式233,能看就行 <style> #page { width: 20px; } </style> <table> & ...

  6. css 重排与重绘

    css 重绘与重排 我们要知道当浏览器下载完页面的所有资源后,就会开始解析源代码. HTML 会被解析成 DOM Tree,Css 则会被渲染成 CSSOM Tree,最后它们会附加到一起,形成渲染树 ...

  7. JavaScript中去除字符串空格的方法

    语法 string.trim() 参数值 无 返回值 类型:string 描述:返回移除头尾空格的字符串 技术细节 JavaScript版本: ECMAScript 5 去除字符串左右两端的空格,在v ...

  8. coding++:js实现基于Base64的编码及解码

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. SpringCloud服务的注册发现--------consul实现服务与发现

    1,consul也可以替代Eureka实现注册和发现的功能,即注册中心. 之前在linux环境通过consul + upsync + nginx 实现nginx 的动态负载均衡 https://www ...

  10. 模块 序列化 json pickle shelv xml

    序列化 序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes. json 模块 json.dump(d,f) json.load(f ...