python 用Snap7读写西门子PLC中DB块

       最近要开发基于TCP/IP协议的西门子S7系列PLC的通讯和数据采集,网上搜罗了一圈发现有python snap7还有HSL这两个工具,不过考虑到商用界限并且鉴于此次开发时间足够,就自己研究上手了,

       由于网上解决方案有限,查阅大部分资料只能查到读一些I/O/M之类的接口,DB块基本没有...无赖只好啃manual。

基本上主要用snap7的read_area 、write_area两个方法就可以实现,当然接口众多...我也就没一一去了解,

       废话少说~~直接贴代码:

 

#####################################################################
# equipmenthandler.py
#
# (c) Copyright 2013-2015, Benjamin Parzella. All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#####################################################################
import struct
import snap7
from snap7.util import *
from snap7.snap7exceptions import Snap7Exception
from snap7.snap7types import *
import EAP.LogFile.communication_log_file_handler

db = \
    """DB001 Real 0.0 7.9
DB002 Bool 4.2 1
DB003 Int 6.0 12
DB004 String 8.0 0221190081
DB005 Real 264.0 9.69"""
offsets = {"Bool":2,"Int":2,"Real":4,"DInt":6,"String":256}

class DATAObject(object):
    pass

class s7netcommunication:
    def __init__(self,ip,port=102,rack=0,slot=0):    

        self.ip=ip
        self.port=port
        self.rack=rack
        self.slot=slot
        self.obj = DATAObject()
        self.client = snap7.client.Client()

    def Connect(self):
        self.client.connect(self.ip, self.rack, self.slot,self.port)
        
    def Disconnect(self):
        self.client.disconnect()

    def get_data_len(self,bytebit,datatype):
        offset_int= []
        offset_int.append(int(bytebit.split('.')[0]))
        data_len = (max(offset_int))+ int(offsets[datatype])
        return data_len

    def ReadDBData(self,device_type,data_num,data_len,name,bytebit,datatype):
            data=''
            if device_type.upper() == 'I':
                #data =  self.client.read_area(0x81,data_num,0,data_len)
                pass
            elif device_type.upper() == 'Q':
                #data =  self.client.read_area(0x82,data_num,0,data_len)
                pass
            elif device_type.upper() == 'M':
                data =  self.client.read_area(0x83,data_num,0,data_len)
                pass
            elif device_type.upper() == 'DB':
                data =  self.client.read_area(0x84,data_num,0,data_len)
           
            value = None
            offset = int(bytebit.split('.')[0])
            if datatype=='Real':
                value = get_real(data,offset)
            if datatype=='Bool':
                bit = int(bytebit.split('.')[1])
                value = get_bool(data,offset,bit)                    
            if datatype=='Int':
                value = get_int(data,offset)            
            if datatype=='String':
                value = get_string(data,offset,256)

            self.obj.__setattr__(name,value)
            return self.obj
        
    def WriteDBData(self,data_num,data_len,bytebit,datatype,value):          
        result =  self.client.read_area(0x84,data_num,0,data_len)
        byte_idx = int(bytebit.split('.')[0])

        if datatype=='Bool':            
            bit_idx = int(bytebit.split('.')[1])
            set_bool(result,byte_idx,bit_idx,value)               
        elif datatype=='Int':
            set_int(result,byte_idx,value)                  
        elif datatype=='Real':
            set_real(result,byte_idx,value)
        elif datatype=='String':
            set_string(result,byte_idx,value,256)

        self.client.write_area(0x84,data_num,0,result)
            

S7Net=s7netcommunication('192.168.0.1',102,0,0)
S7Net.Connect()
itemlist = filter(lambda a:a != ' ',db.split('\n'))
space = ' '
items = [{
                "name":x.split(space)[0],
                "datatype":x.split(space)[1],
                "bytebit":x.split(space)[2],
                "value":float(x.split(space)[3]) if (x.split(space)[1])=='Real' else (str(x.split(space)[3]) if (x.split(space)[1])=='String' else
                                                                                     (bool(int(x.split(space)[3])) if (x.split(space)[1])=='Bool' else 
                                                                                      ((int(x.split(space)[3]) if (x.split(space)[1])=='Int' else None))))
    }for x in itemlist]
obj = DATAObject()
for x in items:
    data_len = S7Net.get_data_len(x['bytebit'] ,x['datatype'])    
    S7Net.WriteDBData(1,data_len,x['bytebit'],x['datatype'],x['value'])
    DATA_obj = S7Net.ReadDBData('DB',1,data_len,x['name'],x['bytebit'] ,x['datatype'])

print(DATA_obj.DB001,DATA_obj.DB002,DATA_obj.DB003,str(DATA_obj.DB004)[0:10],DATA_obj.DB005)

 

你可能感兴趣的:(数据采集,二次开发)