浅析工业数字化如何高效获取数据

1 序言

工业数字化,其实确切的说应该是数据赋能,能够将工业生产的过程数据,运营数据等进行深度挖掘,最终能够结合实际的业务进行辅助决策。
怎么能够高效拿到有用的数据,不造成资源浪费的同时获取到有用的可以进行挖掘的数据,这是值得大家去研究的。
我走过一些进行数字化改造的工业企业,他们的数据采集只是一个简单的Kepserver软件,当他们的数据量很大的时候会出现断线,数据延迟高等等问题,数据采集不只是一个数据接口那么简单,数据采集应该被理解成所有上层应用下面的数据支撑体系,是一个坚实的“地基”,并且要高性能,能够在秒级甚至毫秒级给出响应,并且能够分布式部署,可以轻松进行横向扩展。
之所以出现这种情况是因为很多信息企业不了解工业数据的特点,其实工业数据产生的一瞬间看不出来谁和谁会有关系,也就是说你不做工作是很难通过二维表的形式表达出这个工厂的关系,我觉得这是在数据层面,工业与其他行业信息化的最大不同。

工业数据 Time-Tag-value-Quality

在这里插入图片描述

典型的关系模型 一对多,多对多

在这里插入图片描述

我会在实时数据和历史数据两个层面阐述西门子产品在数据开放性上面的一些特性,文章仅代表我个人观点。希望大牛轻喷。。。

2 实时数据

对于实时数据,先卖个关子,工厂内的实时数据哪里的质量最好,后面的文章中我会用质量这个词来描述数据的优秀程度,比如数据实时性,数据准确性,合理性统称为质量。传感器?很明显不是,因为传感器很少有能够通过以太网能够拿到的,对于现在这个阶段,尽量不要使用串口通讯技术。上位机?没错,上位机是一个不错的选择,可以通过OPCUA的方式在上位机获取到实时数据,很方便,几百上千的数据点在上位机上直接采集可能么有问题,但是数据点很多呢,这些socket链接会不会影响到上位机的性能,这都是未知数。PLC?终于有人想到PLC了,最为工厂中最重要的控制元件,每个扫描周期达到毫秒级的速度,并且每个PLC负责一台设备,一段产线,这些天然的优势,很多时候没有被大家发现,为什么不直接从PLC拿实时数据呢?从PLC拿到的数据就是一个宽泛的“主题库”,因为每台PLC控制不同的设备或者不同的产线,拿到数据后你就不必在做数据拆分,何乐而不为。

在这里插入图片描述我这个架构没有考虑网络安全的因素,不管时什么类型的网络传输,网络安全是必须考虑进去的,网络安全有专业的人去做,我不多赘述(其实我不懂)
redis使用读写分离主从复制的技术架构,通过redis获取到PLC的实时数据,并且为Server提供实时数据,我只用一层架构就能够拿到工厂的实时数据。架构师有一句经典的台词,没有什么问题是加一层解决不了的,如果有,那么就再加一层。这是个真理,但是也有问题,每加一层架构就要增加技术成本,增加维护量,增加出错率,如果能用最简单的架构满足我们的需求,那就是最合适的,工业场景不适合“炫技”,实实在在的稳定是最好的选择。

话不多说,上代码
使用Python通过socket获取1500CPU的数据,1500CPU需要开启远程PUT/GET链接,其他的不用动,占用一个开放链接资源,对于1500系列CPU来说,一个链接的资源对它的性能影响微乎其微。

import socket
from threading import Thread as td
import time
import struct
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
server.bind(('192.168.0.199',2002))
server.listen(128)
client,addr = server.accept()
print('欢迎PLC@%s on %d访问服务器'%(addr[0],addr[1]))
def recv_msg(client):
    while True:
        msg = client.recv(1024)
        msg = struct.unpack('bbbbbbbbbb',msg)
        print(msg)
def send_msg(client):
    msg = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11]
    a = list(map(lambda i: struct.pack('b',i),msg))
    b = b''.join(i for i in a)
    while True:
        time.sleep(1)
        client.send(b)
def main():
    t1 = td(target=recv_msg,args=(client,))
    t2 = td(target=send_msg,args=(client,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
if __name__ == "__main__":
    main()

3 历史数据

说完实时数据,再来聊历史数据,没错,WinCC是获取工业历史数据的很好的途径。WinCC/SQLSERVER提供了标准的OLE-DB数据接口。

3.1 预备知识- 剖析微软数据库组件-ADO OLEDB ODBC

微软是一家“伟大”的公司,嗯,我就不继续吐槽了。
先借用一张图
在这里插入图片描述
ODBC(Open DataBase Connectivity)开放数据库互联。是由微软主导的数据库链接标准。

OLE-DB(Object Linking and Embedding DataBase)对象链接和嵌入数据库。它依赖于COM和提供OLE DB提供者的厂商而非ODBC使用的SQL。

ADO(ActiveX Data Object)ActiveX数据对象。基于OLE-DB建立连接的局部和远程数据库访问技术。同OLE-DB一样要“年轻”些。

3.2 Python 通过OLE-DB获取WinCC历史数据

下面的代码分别通过ODBC和OLEDB链接了Mysql和WinCC/SQLSERVER


import win32com.client


def conn_mysql():
    #DSN = r'Provider=WinCCOLEDBProvider.1;Catalog=CC_test2_20_03_31_16_25_08R;Data Source=ZJF02\WINCC;UID=sa;PWD=root'
    DSN= r"DRIVER={MySQL ODBC 8.0 Unicode Driver}; SERVER=localhost; DATABASE=test; USER=root; PASSWORD=root;OPTION=3"

    #select
    Rs = win32com.client.Dispatch(r"ADODB.Recordset")
    Rs.ActiveConnection = DSN
    Rs.Source = r"select * from testtable"
    Rs.CursorType = 0
    Rs.CursorLocation = 2
    Rs.LockType = 1
    Rs.Open()
    numRows = 0
    Rs.MoveFirst()
    while not Rs.EOF:
    #    print r'id:',Rs.Fields.Item("id").Value.encode('gbk')
    #      if Rs.Fields.Item("name").Value != None:
    #         print r'  name:',Rs.Fields.Item("name").Value.encode('gbk')
    #     numRows+=1
    #     Rs.MoveNext()
    # print 'Total Rows:',numRows

        a = str(Rs.Fields.Item(0))+str(Rs.Fields.Item(1))+str(Rs.Fields.Item(2))+'\n'
        # with open('a.txt', 'a', encoding='utf-8') as f:
        #     f.write(a)
        print(a)
        Rs.MoveNext()

def conn_wincc():
    runTime = win32com.client.Dispatch(r'CCHMIRuntime.HMIRuntime')
    catalog = runTime.Tags("@DatasourceNameRT").Read()  # 获取数据库名称
    # dataSource = runTime.Tags("@LocalMachineName").Read()  # 获取计算机名称
    return catalog

def test():
    DSN = r'Provider=WinCCOLEDBProvider.1;Catalog=CC_data_tes_20_04_22_17_20_56R;Data Source=ZJF02\WINCC;UID=administrator;PWD=kobe0820'
    Rs = win32com.client.Dispatch(r"ADODB.Recordset")
    Rs.ActiveConnection = DSN
    #Rs.Source = r"select * from testtable"
    Rs.Source = r"Tag:R,('pva\t1'),'2020-03-31 10:36:30.870','2020-07-01 04:21:46.990'"
    Rs.CursorType = 0
    Rs.CursorLocation = 3
    Rs.LockType = 1
    Rs.Open()
    numRows = 0
    Rs.MoveFirst()
    #print(Rs.FieldCount)
    while not Rs.EOF:
        print(Rs.Fields.Item(0))
        Rs.MoveNext()

if __name__ == '__main__':
    #print(conn_wincc())
    #conn_mysql()
    test()

4 总结

用合适的方法做事很重要,希望对大家有帮助,再次重申,文章仅代表个人观点。

附件

一、ADO连接
1、连接access数据库
set conn=Server.CreateObject("ADODB.Connection")
conn.open "Driver={Microsoft Access Driver (*.mdb)};dbq="&Server.Mappath("dbname(路径全名)")
2、连接SQL Server数据库
set conn=server.CreateObject("ADODB.Connection")
sql="Driver={SQL Server};server=(local);uid=sa;pwd=sa;database=dbname"
conn.open(sql)

二、ODBC连接(必须先注册数据源---DSN)
(列举配置SQL Server数据库文件DSN,打开管理工具---数据源(ODBC)---打开系统DSN选项卡---单击添加按钮---从列表中选择SQL Server,单击完成---在名称中输入数据库名称,在你想连接的SQL Server服务器中输入(local)---按向导提示完成)
1、连接access数据库
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "DSN=注册名"
2、连接SQL Server数据库
set conn=Server.CreateObject("ADODB.Connection")
conn.connectionstring="DSN=注册名;UID=sa;PWD=sa;"
conn.open

三、OLEDB连接数据库
1、连接access数据库
set conn=Server.CreateObject("ADODB.Connection")
conn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="&server.MapPath("dbname(路径全名)")&";Persist Security Info=False"
set rs=Server.CreateObject("ADODB.Recordset")
2、连接SQL Server数据库
set conn=server.CreateObject("ADODB.Connection")
sql="Provider=SQLOLEDB;data source=(local);initial catalog=dbname;User ID=sa;password=sa;"
conn.open(sql)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kobe_OKOK_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值