Python + OPCUA + s7-1200 + MySql + Grafana实现工业数据可视化看板开发

[复制链接]
查看96170 | 回复0 | 2024-3-23 08:10:14 | 显示全部楼层 |阅读模式
“电气自动化搬砖打工人的IT探索之路”

        随着工业技术的发展,近年来越来越多的数字化、IOT、IT&OT融合等等各种高大上的字眼越来越多的出现在制造业领域。作为一个自动化从业者在眼花缭乱的同时,也确实看到了数字化在工业场景的应用, 未来IT在工业领域中的应用也将越来越多。

        本期内容将介绍如何使用Python通过OPCUA获取西门子S7-1200获取工业数据,并将数据写入到Mysql数据库中,作为Grafana的数据源。选择Python,是因为对于IT小白来讲这个容易上手,Mysql不用说是因为开源&免费,前端选择Grafana是因为兄弟的推荐,就尝试着做一做,基础较弱自己也不会选;先看完成后的效果图,并开启正式的介绍:



开发环境:

工具:Visual Studio Code

Python: 3.10.6

MySql:8.0.32

Grafana: 10.0.3

OPC Server: 西门子S7-1200(熟悉自动化行业的都应该知道,这里不过多解释)

第一章: python 通过OPC UA获取到S7-1200 PLC数据

      OPC UA是一种通信协议,全称为Open Platform Communications Unified Architecture。它是一种面向服务的架构,提供了一种标准化的方式来实现不同设备、系统、平台之间的相互通信和数据交换。在工业领域中应用非常广泛,本次使用西门子S7-1200 PLC内置的OPC UA功能,作为OPC UA服务器,python作为OPC UA 客户端获取服务器数据;

     本次直接使用opcua-python库实现python与opcua的通讯,虽然这个库已经停止更新,但是完成当前的工作已经绰绰有余了,当然还有一个高级的异步库opcua-asyncio,但是我尝试过不怎么会用,只能留着已有再说了;

opcua-python说明文档:https://python-opcua.readthedocs.io/en/latest/

opcua-python 安装:

直接使用PIP安装:

pip install opcua

等待完成后,可通过查看opcua信息查看是否安装完成:
C:\Users\Administrator>pip show opcua
Name: opcua
Version: 0.98.13
Summary: Pure Python OPC-UA client and server library
Home-page: http://freeopcua.github.io/
Author: Olivier Roulet-Dubonnet
Author-email: olivier.roulet@gmail.com
License: GNU Lesser General Public License v3 or later
Location: c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages
Requires: lxml, python-dateutil, pytz
Required-by:
代码实现:

1. 打开VS CODE新建一个.py文件,由于只是作为客户端适用,仅需从opcua库中导入client即可
from opcua import Client

2. 实例化opcua Client,这一步需要写入访问的opcua server的url,如果访问需要账号密码还需要添加账号密码到实例化客户端,由于链接过程中容易出代码参考如下:
while (True):
try:
# 实例化客户端,需要URL参数,timeout可以默认;
        client = Client(url="opc.tcp://192.168.0.80:4840", timeout=60000)
# 账号秘密以实际为准
        client.set_user(opcParams['username'])
        client.set_password(opcParams['password'])
# 客户端链接
        client.connect()
# 链接成功后跳出循环,准备执行数据读取
break
except:
        logger.error("OPCUA链接失败,将在20S后重连;")
        time.sleep(20)

3. 数据读取,opcua是通过NodeID(节点标识)来识别变量的读取,可以通过轮询获取该opc server下的所有节点数据,这个位置我也咩有整明白,暂时留着待以后再研究。这里推荐一个取巧的办法,可以通过UaExpert软件作为OPC Server的测试软件,链接成功后即可看到能访问到的节点信息;鼠标点击节点,即可看到节点对应的名称,有兴趣同学可以看看,此处不再赘述;

节点再opcua库中是以列表的形式存在,由于我读取数据是连贯的,因此可以提前将面部分相同的节点提前配置完成,需要读取数据时再加上相对应的节点信息即可;参考代码如下   
for tag in dataParams:
# 获取震动节点
                vibrateNode = []
                vibrateNode = vibrateNode + \
                    opcParams['rootnode']+["5:Vibrate_Data"]
                vibrateNode.append(f"5:{dataParams[tag]['vibrate']}")
                vibrateValue = client.get_root_node().get_child(vibrateNode).get_value()
                tagValues[f"{dataParams[tag]['vibrate']}"] = round(
                    vibrateValue, 3)

至此,opc ua数据读写完成;(代码中 dataparams是通过json作为配置文件,在python中读取获得),下一篇文章将分享,如何将获取数据写入到数据库,由于代码能力有限,文中表达有不合适的地方请见谅。、

完整代码:

defopcconnect(opcParams):
while (True):
try:
            client = Client(url=opcParams['url'], timeout=60000)
            client.set_user(opcParams['username'])
            client.set_password(opcParams['password'])
            client.connect()
break
except:
            logger.error("OPCUA链接失败,将在20S后重连;")
            time.sleep(20)
return client
# 创建OPC 读取数据

defopcclient(opcParams, dataParams):
    client = opcconnect(opcParams)
while (True):
try:
for tag in dataParams:
# 获取震动节点
                vibrateNode = []
                vibrateNode = vibrateNode + \
                    opcParams['rootnode']+["5:Vibrate_Data"]
                vibrateNode.append(f"5:{dataParams[tag]['vibrate']}")
                vibrateValue = client.get_root_node().get_child(vibrateNode).get_value()
                tagValues[f"{dataParams[tag]['vibrate']}"] = round(
                    vibrateValue, 3)
# 获取电流节点
                currentNode = []
                currentNode = currentNode + \
                    opcParams['rootnode']+["5:Current_Data"]
                currentNode.append(f"5:{dataParams[tag]['current']}")
                currentValue = client.get_root_node().get_child(currentNode).get_value()
                tagValues[f"{dataParams[tag]['current']}"] = round(
                    currentValue, 3)
except:
            logger.error("OPCUA数据读取失败,将在10S后重试;")
            time.sleep(10)
break
        logger.mylog('读取数据完成')
        logger.mylog(tagValues)
        time.sleep(opcParams['cycletime'])

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册哦

x
您需要登录后才可以回帖 登录 | 注册哦

本版积分规则