项目实战4-工控系统前端
这是一个开发 工业控制系统 前端 的锻炼。
可以微信咨询 byhy44
,参加实战班 或者 购买视频讲解和代码 。
您需要高效学习,找工作? 点击咨询 报名实战班
点击查看学员就业情况
项目实战简介
先需要对 矿石采掘场地 开发监控系统, 架构图如下
实战要求: 开发其中的 操作前台
子系统 ,该系统的功能界面如下
锻炼本项目实战,需要具备的基础知识点包括:
-
比较扎实的 Python语言基础
-
比较了解线程、Socket网络编程
-
有一定的 Python Qt 图形界面编程能力
Graphics View 框架
这个程序开发的需要使用 Qt 的 Graphics View 框架
Graphics View
框架让我们可以开发自定义的各种 2D 图形item( QGraphicsItem )
,
并且可以对其进行各种展示和操作控制,比如,线条/大小/颜色/移动/缩放/拖拽/点击行为 等等
Graphics View
框架主要由3种类型对象组成:
Graphics View
框架是典型的 model-view 架构。
这里, QGraphicsScene 和里面包含的 QGraphicsItem 作为 model, QGraphicsView 作为 view
model 里面存储了 要展示的界面的数据定义, 而view根据 model里面的数据进行展示。
一个 model可以对应多个view。
来看一个代码示例
from PySide6 import QtWidgets, QtGui
app = QtWidgets.QApplication()
# 创建 QGraphicsScene 对象,参数设定 位置 和宽度高度
scene = QtWidgets.QGraphicsScene(0, 0, 400, 400)
scene.setBackgroundBrush(QtGui.QColor('#C1E9F5')) # 设定整体背景色
# 创建 QGraphicsView 对象,它是 QWidget的子类, 也是一个QWidget
view = QtWidgets.QGraphicsView(scene)
# 创建QGraphicsRectItem 矩形对象, 这是 QGraphicsItem的子类型
rect = QtWidgets.QGraphicsRectItem(10, 10, 200, 50)
scene.addItem(rect) # 添加到 QGraphicsScene 对象中
rect.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True) # 让其可以移动
view.show()
app.exec()
这里, QGraphicsScene 对象 和里面包含的 QGraphicsRectItem矩形对象 ,就定义了 要展示在view界面的 内容。
前面说过一个model可以对应多个view, 所以,这样可以这样
from PySide6 import QtWidgets, QtCore
app = QtWidgets.QApplication()
scene = QtWidgets.QGraphicsScene(0, 0, 400, 400)
# 创建 2个QGraphicsView 对象, 对应同一个 QGraphicsScene 对象
view1 = QtWidgets.QGraphicsView(scene)
view2 = QtWidgets.QGraphicsView(scene)
rect = QtWidgets.QGraphicsRectItem(10, 10, 200, 50)
scene.addItem(rect)
rect.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
# 2个view放到 QSplitter里面
splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
splitter.addWidget(view1)
splitter.addWidget(view2)
splitter.show()
app.exec()
运行就可以发现,出现的2个 QGraphicsView 展示的 内容是一样的,包括在移动的时候,行为也是一样的。
因为这2个view对应的是同一个model。
内置的item
可以看出,这种界面的开发, 主要就是开发各种 图形item
: QGraphicsItem。
有些 QGraphicsItem 需要自己开发 , 有些可以直接使用 Qt 提供的现成的 QGraphicsItem。
我们先来看 Qt 提供的一些 图形item , 他们都是 QGraphicsItem 的子类
矩形
官网链接 : QGraphicsRectItem
前面的示例中已经演示过,呈现出的是一个矩形。
# 前2个参数指定了该矩形显示在上级对象的x/y坐标位置,
# 后2个参数指定了矩形的宽度和高度
rect = QtWidgets.QGraphicsRectItem(10, 10, 200, 50)
如果想在运行过程中,动态改变矩形的宽度,高度,可以使用 setRect
方法
比如
from PySide6 import QtWidgets
app = QtWidgets.QApplication()
scene = QtWidgets.QGraphicsScene(0, 0, 300, 300)
view = QtWidgets.QGraphicsView(scene)
rect = QtWidgets.QGraphicsRectItem(10, 10, 200, 50)
scene.addItem(rect)
def changeWidthHeight():
# 返回值为 `QRectF` 对象
qrf = rect.rect()
qrf.setWidth(100)
qrf.setHeight(30)
rect.setRect(qrf) # 重新设定
btn = QtWidgets.QPushButton('改变宽高')
btn.clicked.connect(changeWidthHeight)
top = QtWidgets.QWidget()
top.resize(400,400)
layout = QtWidgets.QVBoxLayout(top)
layout.addWidget(view)
layout.addWidget(btn)
top.show()
app.exec()
添加内置item,还有一种快捷方法,使用 QGraphicsScene 的 addXXX
系列方法,比如
from PySide6 import QtWidgets
app = QtWidgets.QApplication()
scene = QtWidgets.QGraphicsScene(0, 0, 300, 300)
view = QtWidgets.QGraphicsView(scene)
# 快捷方法添加矩形item,返回值就是添加的 QGraphicsRectItem对象
rect = scene.addRect(10, 10, 200, 50)
view.show()
app.exec()
可以通过 设置画笔和画刷来指定 item的边线样式 和 填充色,比如
from PySide6 import QtWidgets, QtGui
app = QtWidgets.QApplication()
scene = QtWidgets.QGraphicsScene(0, 0, 300, 300)
view = QtWidgets.QGraphicsView(scene)
rect = scene.addRect(10, 10, 200, 50)
brush = QtGui.QBrush(QtGui.QColor('#C1E9F5')) # 设定填充色
rect.setBrush(brush)
pen = QtGui.QPen(QtGui.QColor('green')) # 设定线条颜色
pen.setWidth(3) # 设定线条宽度
rect.setPen(pen)
view.show()
app.exec()
椭圆
官网链接 : QGraphicsEllipseItem
示例代码
from PySide6 import QtWidgets, QtGui
app = QtWidgets.QApplication()
scene = QtWidgets.QGraphicsScene(0, 0, 300, 300)
view = QtWidgets.QGraphicsView(scene)
# 设定去锯齿,否则椭圆边线会有明显的锯齿
view.setRenderHint(QtGui.QPainter.Antialiasing)
# 参数为椭圆所在矩形的左上角坐标和 椭圆的宽度,高度
elp = QtWidgets.QGraphicsEllipseItem(10, 10, 200, 50)
scene.addItem(elp)
# 当然也可以使用 快捷方法 elp = scene.addEllipse(10, 10, 200, 50)
rect = scene.addRect(10, 10, 200, 50)
view.show()
app.exec()
线条
官网链接 : QGraphicsLineItem
示例代码
from PySide6 import QtWidgets, QtGui
app = QtWidgets.QApplication()
scene = QtWidgets.QGraphicsScene(0, 0, 300, 300)
view = QtWidgets.QGraphicsView(scene)
# 设定去锯齿,否则斜线会有明显的锯齿
view.setRenderHint(QtGui.QPainter.Antialiasing)
# 参数为线条的起点,终点坐标
line = QtWidgets.QGraphicsLineItem(10, 10, 200, 30)
scene.addItem(line)
# 当然也可以使用 快捷方法 line = scene.addLine(10, 10, 200, 30)
pen = QtGui.QPen(QtGui.QColor('green')) # 设定线条颜色
pen.setWidth(1) # 设定线条宽度
line.setPen(pen)
view.show()
app.exec()
文本
官网链接 : QGraphicsTextItem
示例代码
from PySide6 import QtWidgets, QtGui
app = QtWidgets.QApplication()
scene = QtWidgets.QGraphicsScene(0, 0, 300, 300)
view = QtWidgets.QGraphicsView(scene)
# 参数为文字内容
text = QtWidgets.QGraphicsTextItem(
''' 白月黑羽项目实战4
开发一个矿工监控系统,使用各种item,实时显示监控画面
''')
scene.addItem(text)
# 设定颜色
text.setDefaultTextColor(QtGui.QColor(0x0074cc))
# 设定字体大小
font = QtGui.QFont()
font.setPointSize(12)
text.setFont(font)
font.setFamily('新宋体')
# 设定文本段宽度,像素为单位
text.setTextWidth(200)
# 可以使用下面setPlainText方法,动态改变显示内容
# text.setPlainText('新的显示内容')
view.show()
app.exec()
位图
官网链接 : QGraphicsPixmapItem
QGraphicsPixmapItem可以显示位图图片,比如 bmp/jpg/png 等
示例代码
from PySide6 import QtWidgets, QtGui, QtCore
app = QtWidgets.QApplication()
# 对于显示器使用了缩放的,PySide6需要加上这行,否则图片显示毛糙
# 而PySide2就不需要,应该是Qt6的bug,
# 我已经给Qt提交了bug : https://bugreports.qt.io/browse/PYSIDE-2426
app.setHighDpiScaleFactorRoundingPolicy(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.Round)
scene = QtWidgets.QGraphicsScene(0, 0, 300, 300)
view = QtWidgets.QGraphicsView(scene)
# 创建QPixmap对象
pm = QtGui.QPixmap('images/camera.png')
# 设定图片缩放大小
pm = pm.scaledToWidth(50, QtCore.Qt.SmoothTransformation)
# 创建 QGraphicsPixmapItem对象
picture = QtWidgets.QGraphicsPixmapItem(pm)
scene.addItem(picture)
view.show()
app.exec()
一些设定
属性设定
比较常见的item属性设定有如下设置:
ItemIsMovable # 设置item可以移动
ItemIsSelectable # 设置item可以选中
ItemIsFocusable # 设置item可以聚焦,才会有键盘按键回调keyPressEvent
下面是示例代码
from PySide6 import QtWidgets, QtGui, QtCore
app = QtWidgets.QApplication()
app.setHighDpiScaleFactorRoundingPolicy(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.Round)
scene = QtWidgets.QGraphicsScene(0, 0, 300, 300)
view = QtWidgets.QGraphicsView(scene)
pm = QtGui.QPixmap('images/camera.png')
pm = pm.scaledToWidth(50, QtCore.Qt.SmoothTransformation)
picture = QtWidgets.QGraphicsPixmapItem(pm)
scene.addItem(picture)
# 设置item可以移动
picture.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
# 设置item可以选中
picture.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)
# 设置item可以聚焦,这样才会有键盘按键回调keyPressEvent
picture.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable, True)
view.show()
app.exec()
改变item的位置
如果在程序运行过程中需要改变item(相对于上级)的位置, 可以使用 setPos
方法
组合item
官网链接 : QGraphicsItemGroup
有时,我们需要两种item组合为一个 item使用, 比如 带文字的图标 item(气体监测仪等)。
这时候,可以使用 组合item: QGraphicsItemGroup
示例如下:
from PySide6 import QtWidgets,QtGui
from PySide6.QtCore import Qt
app = QtWidgets.QApplication()
app.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.Round)
# 组合item继承自 QGraphicsItemGroup
class PictureItem(QtWidgets.QGraphicsItemGroup):
def __init__(self, pic, text):
super().__init__()
pm = QtGui.QPixmap(pic).scaledToWidth(40, Qt.SmoothTransformation)
self.picItem = QtWidgets.QGraphicsPixmapItem(pm)
self.picItem.setPos(0,0) # 设置其在parent的显示位置
self.textItem = QtWidgets.QGraphicsTextItem()
self.textItem.setTextWidth(70)
self.textItem.setPlainText(text)
self.textItem.setPos(40,10) # 设置其在parent的显示位置
# 添加子item到组item中
self.addToGroup(self.picItem)
self.addToGroup(self.textItem)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
scene = QtWidgets.QGraphicsScene(0, 0, 800, 600)
view = QtWidgets.QGraphicsView(scene)
item = PictureItem('./images/temp-meter.png', '分析仪')
item.setPos(100, 100)
scene.addItem(item)
view.show()
app.exec()
自定义item
有些复杂的图形,可以使用上面讲的 位图item, 寻找或自己绘制图片,比如项目实战里面的摄像头/空气监测仪 等等。
但是如果这些还需要item显示内容/效果 随着业务数据的变化而变化,比如项目实战里面的 风泵/水箱, 使用位图item就往往就力不从心了。
这时就需要我们 自己定义item。
本节内容仅供内部学员学习。
您需要高效学习,找工作? 点击咨询 报名实战班
点击查看学员就业情况
分阶段开发项目
本次练习需要的文件放在如下百度云盘目录中,根据后续练习说明下载需要的文件。
01 初始布局
界面初始布局,左边是item图标栏,右边是 操作区
在项目实战的云盘目录中有个 images.zip
文件,下载并且解压
里面有提供好的图标栏中需要的 图标图片文件,省去自己寻找图标图片的时间。
参考代码如下,对应实现讲解 见视频说明
from PySide6 import QtWidgets,QtGui,QtCore
PIC_LIST = [
'gas-meter', 'temp-meter',
'wind-meter', 'water-meter',
'water-valve', 'water-tank',
'air-pump', 'camera',
'hydrant', 'pipeline'
]
class MWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.resize(1000, 800)
# central Widget
centralWidget = QtWidgets.QWidget(self)
self.setCentralWidget(centralWidget)
# central Widget 里面的 主 layout
self.mainLayout = QtWidgets.QHBoxLayout(centralWidget)
# 左边区
self.setupLeftPane()
# 中间绘制区
self.setupCanvas()
def setupLeftPane(self):
leftLayout = QtWidgets.QVBoxLayout()
self.mainLayout.addLayout(leftLayout)
pixmapLayout = QtWidgets.QGridLayout()
leftLayout.addLayout(pixmapLayout)
leftLayout.addStretch()
row, col = 0, 0
for picName in PIC_LIST:
# 初始参数就是图片路径名
pixmap = QtGui.QPixmap(f'./images/{picName}.png')
# 设定图片缩放大小,这里是50个像素的宽度,高度也会等比例缩放
pixmap = pixmap.scaledToWidth(40, QtCore.Qt.SmoothTransformation)
label = QtWidgets.QLabel()
# 设置label显示的pixmap
label.setPixmap(pixmap)
pixmapLayout.addWidget(label, row, col) # 添加到第1行,第1列
if col == 1:
row += 1
col = 0
else:
col += 1
def setupCanvas(self):
self.scene = QtWidgets.QGraphicsScene(0, 0, 800, 600)
self.view = QtWidgets.QGraphicsView(self.scene)
self.mainLayout.addWidget(self.view)
app = QtWidgets.QApplication()
app.setHighDpiScaleFactorRoundingPolicy(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.Round)
window = MWindow()
window.show()
app.exec()
02 拖放布局
实现 item图标拖放到 操作区 的功能,并且item在操作区能够用鼠标移动
参考代码如下,对应实现讲解 见视频说明
from PySide6 import QtWidgets,QtGui,QtCore
from PySide6.QtCore import Qt
PIC_LIST = [
'gas-meter', 'temp-meter',
'wind-meter', 'water-meter',
'water-valve', 'water-tank',
'air-pump', 'camera',
'hydrant', 'pipeline'
]
class DragLabel(QtWidgets.QLabel):
def mouseMoveEvent(self, e):
if e.buttons() != Qt.LeftButton:
return
mimeData = QtCore.QMimeData()
drag = QtGui.QDrag(self)
drag.setMimeData(mimeData)
drag.exec(Qt.DropActions.MoveAction)
class DnDGraphicView(QtWidgets.QGraphicsView):
def dragMoveEvent(self, e):
pass
def dragEnterEvent(self, e):
if True:
e.accept()
else:
e.ignore()
def dropEvent(self, e):
picName = e.source().dndinfo['name']
pixmap = QtGui.QPixmap(f'./images/{picName}.png')
pixmap = pixmap.scaledToWidth(40, Qt.SmoothTransformation)
item = QtWidgets.QGraphicsPixmapItem(pixmap)
self.scene().addItem(item)
item.setPos(e.position())
# 设置item可以移动
item.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
# 设置item可以选中
item.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)
# 设置item可以聚焦,这样才会有键盘按键回调keyPressEvent
item.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable, True)
# 该方法使得view 改变大小时(比如拖拽主窗口resize), scene大小跟着变化
# 否则,view和secen大小不一致, 拖放item 时,位置就不对了。
def resizeEvent(self, event):
super().resizeEvent(event)
size = event.size()
self.setSceneRect(0, 0, size.width(), size.height())
class MWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.resize(1000, 800)
# central Widget
centralWidget = QtWidgets.QWidget(self)
self.setCentralWidget(centralWidget)
# central Widget 里面的 主 layout
self.mainLayout = QtWidgets.QHBoxLayout(centralWidget)
# 左边区
self.setupLeftPane()
# 中间绘制区
self.setupCanvas()
def setupLeftPane(self):
leftLayout = QtWidgets.QVBoxLayout()
self.mainLayout.addLayout(leftLayout)
pixmapLayout = QtWidgets.QGridLayout()
leftLayout.addLayout(pixmapLayout)
leftLayout.addStretch()
row, col = 0, 0
for picName in PIC_LIST:
# 初始参数就是图片路径名
pixmap = QtGui.QPixmap(f'./images/{picName}.png')
# 设定图片缩放大小,这里是50个像素的宽度,高度也会等比例缩放
pixmap = pixmap.scaledToWidth(40, Qt.SmoothTransformation)
label = DragLabel()
label.dndinfo = {'name': picName}
# 设置label显示的pixmap
label.setPixmap(pixmap)
pixmapLayout.addWidget(label, row, col)
if col == 1:
row += 1
col = 0
else:
col += 1
def setupCanvas(self):
self.scene = QtWidgets.QGraphicsScene(0, 0, 800, 600)
self.view = DnDGraphicView(self.scene)
self.mainLayout.addWidget(self.view)
app = QtWidgets.QApplication()
app.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.Round)
window = MWindow()
window.show()
app.exec()
03 矩形/线条/椭圆/文字 item
实现 位图item 支持配套文字,并且支持 用键盘方向键 进行 像素级微小移动。
添加 矩形/线条/椭圆/文字 item
04 属性表格-上
然后界面添加属性表格,属性表格的样式风格和视频说明里面一致。
且有 调整 表格 和 操作区 之间的边界位置的功能。
实现 操作组 选中 下面各类型item,可以配置如下属性
- 文字Item
- 线条Item
- 矩形Item
{
'矩形长度' : '160',
'矩形高度' : '100',
'填充颜色' : '222, 241, 255, 0',
'线条宽度' : '1',
'线条颜色' : '0, 100, 0',
'zValue' : '0.0',
}
- 椭圆Item
{
'椭圆长度' : '160',
'椭圆高度' : '100',
'填充颜色' : '222, 241, 255, 0',
'线条宽度' : '1',
'线条颜色' : '0, 100, 0',
'zValue' : '0.0',
}
- 图片Item
本次练习只要求做到,点击操作区的item,显示其要配置的内容即可。
具体配置功能,下次练习实现
05 属性表格-下
接着上次已经实现的 点击操作区的item,显示其要配置的内容
本次练习完成具体配置功能,就是修改配置项内容,对应操作区item相应改变
06 删除 和 存盘
-
实现图标工具栏,里面有
保存,加载,删除,清空
按钮。 -
保存,加载 功能
-
实现 删除Item,清空操作区的 Item 功能
-
实现 拖放一个Item 就设置为当前选中Item
07 连接后端,获取数据
点击这里 了解采掘工控系统前后端接口的 接口协议格式说明
实现前端连接后端, 能持续接收后端发送过来的数据,打印出接收的每个完整消息的字节串数据即可。
另外,要求能够做到,当服务端重启后,前端能自动重连。
这次练习需要运行后端系统,在本次项目实战的云盘目录中有个 mine-cc.zip
文件,下载并且解压。
苹果Mac电脑下载 苹果Mac电脑
目录里面的 mine-cc-mac.zip
文件,并且解压。
后端系统需要用激活码联网激活,请和老师联系获取激活码后,运行目录里面的 activate.bat
激活。
激活后,运行 run.bat
运行后端服务系统
后端服务等待前端 TCP 连接的 listen 地址端口是 127.0.0.1:47554
,
这个参数可以在 cfg.toml
里面配置
08 某些图片item有额外属性
下面这些图片item的属性,要比前面说的多出一个属性 设备编号
而 camera 摄像头
item 要多处2个属性:设备编号
和 视频流地址
请修改代码支持这些额外属性的 显示/修改/保存/加载
09 显示设备通知消息
后端会发送设备通知消息,消息类型 为 notify-to-frontend
,
各种设备的通知消息,格式示例如下
# 毒气监测仪
BF01|notify-to-frontend|0|1695899578730990${
"device-sn":"aaaa0001","CO":0.05,"HCl":0.01,"SO2":0.01}
# 温度湿度计
BF01|notify-to-frontend|0|1695691644857589${
"device-sn":"aaaa0002","humidity":51.85,"temperature":25.56}
# 空气流量仪
BF01|notify-to-frontend|0|1695899575700207${
"device-sn":"aaaa0003","flow-rate":0.94}
# 水流量表
BF01|notify-to-frontend|0|1695899573726278${
"device-sn":"aaaa0004","flow-rate":95.93,"water-pressure":3120.17}
# 饮用水箱
BF01|notify-to-frontend|0|1695899575825435${
"device-sn":"aaaa0005","water-amount":0.61}
消息体中 device-sn
字段决定了是哪个设备上的通知消息,
要求,先在操作区拖动创建上述5种设备设备, 根据上面 device-sn
填入对应的设备号,然后保存操作区。
继续开发我们的程序,能显示接收到的服务端通知消息内容 到操作区对应的设备图标上。
10 水缸动态显示水量
学习本章上面 自定义item
这一节内容,实现 水缸Item 动态显示水量 的功能
-
正确显示水量百分比,一个水箱的设备编号是 :
aaaa0005
-
能够移动
-
选中时显示边界
-
属性里面包括:
zValue
和设备编号
-
存盘/加载 没有问题
11 直播摄像头
做到双击摄像头,就可以播放该摄像头对应的直播视频流。
12 模式切换
- 查看模式/编辑模式
查看模式 不能 拖拽创建/移动/删除 Item, 但是可以选中,可以编辑属性
- del按键删除元件
可以删除多选的多个元件
- 创建并保存如下操作区设置
上图中2个施工地的设备编号如下
施工地1:
设备类型: 毒气监测仪
设备编号: aaaa0001
设备类型: 温度湿度计
设备编号: aaaa0002
设备类型: 空气流量仪
设备编号: aaaa0003
设备类型: 水流量表
设备编号: aaaa0004
设备类型: 饮用水箱
设备编号: aaaa0005
设备类型: 摄像头
设备编号: aaaa0006
视频流地址: rtmp://127.0.0.1/mytv/room01
施工地2:
设备类型: 毒气监测仪
设备编号: aaaa0021
设备类型: 温度湿度计
设备编号: aaaa0022
设备类型: 空气流量仪
设备编号: aaaa0023
设备类型: 水流量表
设备编号: aaaa0024
设备类型: 饮用水箱
设备编号: aaaa0025
设备类型: 摄像头
设备编号: aaaa0026
视频流地址: rtmp://127.0.0.1/mytv/room02
13 实时统计图
后端会不断上报 煤产量 和 水/电 消耗数据,格式如下
BF01|notify-to-frontend|0|1695691644857589${
"device-sn": "stats",
"coal-1": [37856, 37859, 37866, 37866, 37866, 37872, 37872, 37878, 37883, 37884],
"coal-2": [37645, 37652, 37652, 37652, 37653, 37659, 37663, 37665, 37665, 37668],
"w-used": [37647, 37649, 37651, 37658, 37660, 37666, 37666, 37673, 37678, 37680],
"e-used": [21599, 21602, 21605, 21606, 21607, 21607, 21608, 21610, 21612, 21616]
}
其中:
coal-1
和 coal-2
分别是 煤品1
和 煤品2
的 产量变化数据,单位是吨。
w-used
是 水
消耗数据,单位是吨。
e-used
是 电
消耗数据,单位是千瓦时。
要求在操作区底部呈现3张实时统计图,展示 煤品1
和 煤品2
的 产量数据, 水/电
的消耗数据
14 风泵动画效果
要求完成自定义风泵的功能。
风泵可以根据下方3个风速按钮进行3种速度的旋转,并且点击按钮时发送 device_control
消息给后端 ,告知调整对应风泵的速度
发送消息格式如下
BF01|device_control|0|1695691644857589$
{
"device-sn" : "bbbb0003",
"operation" : "set-wind-pump-speed",
"fan-speed" : 3
}
两个风泵的设备号分别是 bbbb0003
和 bbbb0023
, 这两个风泵 分别对应 空气流量仪 aaaa0003
和 aaaa0023
fan-speed
取值为 0/1/2/3
对应从低到高4种风速, 0
为 零风速
发送消息使用的tcp socket 也就是接收消息的 socket