本小节继续演示如何在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. Github搜索技巧整理

    Github官方网址:https://github.com/ 一.详细官方文档:https://help.github.com/en/github/searching-for-information- ...

  2. 简单java队列

    队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作. LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用. 以下实例演示了队 ...

  3. 两片74门实现的双边沿D触发器

    最近一个项目需要时钟上升沿和下降沿都可以触发的D触发器,但并没有找到符合要求的商品IC.也去看了一些文献,但都是给的示意图然后用分立元件实现的(应该是准备做成IC).这里给出一种最少2个IC就能搭出来 ...

  4. leetcode签到 892. 三维形体的表面积

    题目 三维形体的表面积 在 N * N 的网格上,我们放置一些 1 * 1 * 1 的立方体. 每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上. 请你返回最 ...

  5. Spring----注释----开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别

    来源:http://www.cnblogs.com/leiOOlei/p/3713989.html <context:annotation-config> 和 <context:co ...

  6. PyTorch专栏(五):迁移学习

    专栏目录: 第一章:PyTorch之简介与下载 PyTorch简介 PyTorch环境搭建 第二章:PyTorch之60分钟入门 PyTorch入门 PyTorch自动微分 PyTorch神经网络 P ...

  7. 机器学习算法系列:FM分解机

    在线性回归中,是假设每个特征之间独立的,也即是线性回归模型是无法捕获特征之间的关系.为了捕捉特征之间的关系,便有了FM分解机的出现了.FM分解机是在线性回归的基础上加上了交叉特征,通过学习交叉特征的权 ...

  8. Tainted canvases may not be exported的问题解决

    项目里使用到用canvas生成海报,在toDataURL报了这个错误Tainted canvases may not be exported. 原因就在于使用了跨域的图片,所以说是被污染的画布.解决方 ...

  9. 图解JVM类加载机制和双亲委派模型

    我们都知道以 .java 结尾的 Java 源文件,经过编译之后会变成 .class 结尾的字节码文件.JVM 通过类加载器来加载字节码文件,然后再执行程序. 什么时候加载一个类 那么,什么时候类加载 ...

  10. 面试必备:详解Java I/O流,掌握这些就可以说精通了?

    @TOC Java IO概述 IO就是输入/输出.Java IO类库基于抽象基础类InputStream和OutputStream构建了一套I/O体系,主要解决从数据源读入数据和将数据写入到目的地问题 ...