“电气自动化搬砖打工人的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']) |