def write(self, client: Client) -> None: """ Write current data to db in plc """ if not isinstance(self._bytearray, DB): raise TypeError( f"Value self._bytearray: {self._bytearray} is not from type DB." ) if self.row_size < 0: raise ValueError("row_size must be greater equal zero.") db_nr = self._bytearray.db_number offset = self.db_offset data = self.get_bytearray()[offset:offset + self.row_size] db_offset = self.db_offset # indicate start of write only area of row! if self.row_offset: data = data[self.row_offset:] db_offset += self.row_offset if self.area == Areas.DB: client.db_write(db_nr, db_offset, data) else: client.write_area(self.area, 0, db_offset, data)
def write(self, client: Client) -> None: """Write current data to db in plc Args: client: :obj:`Client` snap7 instance. Raises: :obj:`TypeError`: if the `_bytearray` is not an instance of :obj:`DB` class. :obj:`ValueError`: if the `row_size` is less than 0. """ if not isinstance(self._bytearray, DB): raise TypeError( f"Value self._bytearray: {self._bytearray} is not from type DB." ) if self.row_size < 0: raise ValueError("row_size must be greater equal zero.") db_nr = self._bytearray.db_number offset = self.db_offset data = self.get_bytearray()[offset:offset + self.row_size] db_offset = self.db_offset # indicate start of write only area of row! if self.row_offset: data = data[self.row_offset:] db_offset += self.row_offset if self.area == Areas.DB: client.db_write(db_nr, db_offset, data) else: client.write_area(self.area, 0, db_offset, data)
def read(self, client: Client) -> None: """Read current data of db row from plc. Args: client: :obj:`Client` snap7 instance. Raises: :obj:`TypeError`: if the `_bytearray` is not an instance of :obj:`DB` class. :obj:`ValueError`: if the `row_size` is less than 0. """ if not isinstance(self._bytearray, DB): raise TypeError( f"Value self._bytearray:{self._bytearray} is not from type DB." ) if self.row_size < 0: raise ValueError("row_size must be greater equal zero.") db_nr = self._bytearray.db_number if self.area == Areas.DB: bytearray_ = client.db_read(db_nr, self.db_offset, self.row_size) else: bytearray_ = client.read_area(self.area, 0, 0, self.row_size) data = self.get_bytearray() # replace data in bytearray for i, b in enumerate(bytearray_): data[i + self.db_offset] = b
def setUp(self): self.databus = conpot_core.get_databus() self.databus.initialize('conpot/templates/snap7_server/template.xml') args = namedtuple('FakeArgs', '') logger.setLevel(logging.WARNING) self.snap7_instance = Snap7Server( 'conpot/templates/snap7_server/snap7/snap7.xml', 'none', args) gevent.spawn(self.snap7_instance.start, '127.0.0.1', 60102) gevent.sleep(0.5) self.server_port = 60102 self.client = Client() self.client.create() self.client.connect("127.0.0.1", 0, 0, tcpport=self.server_port)
def plc_connect(plc): client = Client() try: client.connect( address=plc['ip'], rack=plc['rack'], slot=plc['slot'], ) except Snap7Exception as e: logging.warning('PLC连接失败 ip:{} rack:{} slot:{}'.format(plc['ip'], plc['rack'], plc['slot']) + str(e)) id_num = r.get('id_num') connect_plc_err( id_num, plc_id=plc['id'], ) return client
class PLC: online = False debug = False camera_number: int def __init__(self, camera_number, config_file='config.yml') -> None: self.load_config(config_file) self.camera_number = camera_number self.client = Client() def load_config(self, config_file='config.yml') -> None: with open(config_file) as file: config = yaml.safe_load(file)['plc'] self.enabled = config['enabled'] self.ip = config['ip'] self.rack = config['rack'] self.slot = config['slot'] self.db_read: dict = config['db_read'] self.db_write: dict = config['db_write'] self.update_time = config['update_time'] self.debug = config['debug'] def connect(self) -> None: if not self.enabled: return logger.info( 'PLC is Disabled, change config file to start communication') if self.client: try: self.client.connect(self.ip, self.rack, self.slot) self.online = True logging.info( f"PLC Connected to {self.ip} Rack {self.rack} Slot {self.slot}" ) except Exception as e: logging.exception( f"connect::Failed to connect to PLC {self.ip} " + str(e)) def read(self) -> bytearray: try: db = self.db_read start = db['size'] * self.camera_number return self.client.db_read(db['number'], start, db['size']) except Exception as e: logger.exception(e) def write(self, _bytearray: bytearray) -> None: try: db = self.db_write start = db['size'] * self.camera_number self.client.db_write(db['number'], start, _bytearray) except Exception as e: logger.exception(e) def disconnect(self): self.online = False self.client.disconnect()
def read(self, client: Client) -> None: """ read current data of db row from plc """ if not isinstance(self._bytearray, DB): raise TypeError( f"Value self._bytearray:{self._bytearray} is not from type DB." ) if self.row_size < 0: raise ValueError("row_size must be greater equal zero.") db_nr = self._bytearray.db_number if self.area == Areas.DB: bytearray_ = client.db_read(db_nr, self.db_offset, self.row_size) else: bytearray_ = client.read_area(self.area, 0, 0, self.row_size) data = self.get_bytearray() # replace data in bytearray for i, b in enumerate(bytearray_): data[i + self.db_offset] = b
def __init__(self, ip='192.168.0.1'): self.ip = ip self.INByteArray = bytearray([0, 0]) self.MKByteArray = bytearray([0, 0]) self.threadStatus = False self.varsdict = {} self.threads = {} self.plc = PlcClient() self.subNodes = [] self.subNodesD = {} self.keysDict = {} self.inNodes = {}
class SiemensPlc(SmartTags): def __init__(self, ipaddr, name=None): self.ipaddr = ipaddress.IPv4Address(ipaddr) self.name = name self._port = 102 self._client = Client() self.SmartTags = SmartTags(self) def connect(self): return self._client.connect(self.ipaddr, 0, 0, self.port) def get_connected(self): return self._client.get_connected() def disconnect(self): return self._client.disconnect() def get_plc_state(self): return self._client.get_cpu_state() def get_plc_info(self): return self._client.get_cpu_info() def get_datetime(self): return self._client.get_plc_datetime()
def plc_client(ip, rack, slot, plc_id): """ 建立plc连接的上下文管理器 :param ip: :param rack: :param slot: :return: """ client = Client() try: client.connect(ip, rack, slot) except Snap7Exception as e: logging.warning('连接plc失败' + str(e)) session = Session() id_num = r.get('id_num') alarm = connect_plc_err(id_num, plc_id) session.add(alarm) session.commit() yield client client.disconnect() client.destroy()
from snap7.client import Client from snap7.util import * from snap7.snap7exceptions import Snap7Exception from snap7.snap7types import * IP = '127.0.0.1' PORT = 8088 RACK = 0 SLOT = 0 client = Client() client.connect(IP, RACK, SLOT, PORT) with open('lecturas/db0.txt', 'r') as f: layout = f.read() db_number = 0 all_data = client.db_get(db_number) db1 = DB( db_number, # the db we use all_data, # bytearray from the plc layout, # layout specification DB variable data 6 + 2, # size of the specification 17 is start 1, # number of row's / specifications ) [print(db) for db in db1] with open('lecturas/marcas.txt', 'r') as f: layout = f.read() all_data = client.read_area(S7AreaMK, 0, 0, 10) db2 = DB(
class PLC: def __init__(self, ip='127.0.0.1', name='Default Plc'): self.ip = ip self.name = name self.read_client = Client() self.write_client = Client() self.SmartTags = SmartTags(self) def __repr__(self): return f"{self.name} @ {self.ip}" def __str__(self): return f"{self.name} @ {self.ip}" def connect(self): if self.read_client.get_connected( ) and self.write_client.get_connected(): return True try: if not self.read_client.get_connected(): self.read_client.connect(self.ip, 0, 0) if not self.write_client.get_connected(): self.write_client.connect(self.ip, 0, 0) except Snap7Exception as e: logger.error(str(e)) return False return self.read_client.get_connected( ) and self.write_client.get_connected() def disconnect(self): self.read_client.disconnect() self.write_client.disconnect() def read(self, db, start, length): try: return self.read_client.read_area(S7AreaDB, db, start, length) except Exception as e: if 'CLI : Job pending' in str(e): return self.read(db, start, length) else: raise e def write(self, db, start, data): try: return self.read_client.write_area(S7AreaDB, db, start, data) except Exception as e: if 'CLI : Job pending' in str(e): return self.write(db, start, data) else: raise e
class TestBase(unittest.TestCase): def setUp(self): self.databus = conpot_core.get_databus() self.databus.initialize('conpot/templates/snap7_server/template.xml') args = namedtuple('FakeArgs', '') logger.setLevel(logging.WARNING) self.snap7_instance = Snap7Server( 'conpot/templates/snap7_server/snap7/snap7.xml', 'none', args) gevent.spawn(self.snap7_instance.start, '127.0.0.1', 60102) gevent.sleep(0.5) self.server_port = 60102 self.client = Client() self.client.create() self.client.connect("127.0.0.1", 0, 0, tcpport=self.server_port) def tearDown(self): self.client.disconnect() gevent.sleep(1) self.snap7_instance.stop() def test_info(self): expected = { 'ModuleTypeName': 'Some CPU', 'SerialNumber': '123456789', 'ASName': 'Some system', 'Copyright': 'Someone', 'ModuleName': 'Some PLC' } info = self.client.get_cpu_info() param_list = [param[0] for param in info._fields_] result = {} for param in param_list: result[param] = getattr(info, param) self.assertSequenceEqual(expected.keys(), result.keys()) for key, val in result.items(): self.assertEquals(expected[key], val) def test_cpu_state(self): expected = "S7CpuStatusRun" state = self.client.get_cpu_state() self.assertEquals(state, expected) def test_cpu_stop(self): expected = "S7CpuStatusStop" self.client.plc_stop() state = self.client.get_cpu_state() self.assertEquals(state, expected) def test_cpu_start(self): expected = "S7CpuStatusRun" self.client.plc_stop() self.client.plc_cold_start() state = self.client.get_cpu_state() self.assertEquals(state, expected) self.client.plc_stop() self.client.plc_hot_start() self.assertEquals(state, expected) def test_read_db_default_values(self): # Read database 1, which has a default initialization of all zeroes db_data = self.client.db_read(1, 0, 2) self.assertSequenceEqual(db_data, [0, 0]) def test_read_db_initialized_values(self): # Read database 2, which has configured initial values (1, 0 ,- ,1) db_data = self.client.db_read(2, 0, 4) self.assertSequenceEqual(db_data, [1, 0, 0, 1]) def test_read_db_out_of_range_values(self): size = self.snap7_instance.event_handler.dbs['s7comm_db1']['size'] with self.assertRaises(Snap7Exception): self.client.db_read(1, 0, size + 1) def test_write_read_db(self): expected = [1, 0] self.client.db_write(1, 1, bytearray([0])) self.client.db_write(1, 0, bytearray([1])) db_data = self.client.db_read(1, 0, 2) output_list = [] for data in db_data: output_list.append(data) self.assertSequenceEqual(output_list, expected)
def __init__(self, ip='127.0.0.1', name='Default Plc'): self.ip = ip self.name = name self.read_client = Client() self.write_client = Client() self.SmartTags = SmartTags(self)
from snap7.client import Client SERVER_IP = '127.0.0.100' SERVER_PORT = 102 client = Client() client.connect('127.0.0.100', 0, 2, SERVER_PORT) try: print(client.get_plc_datetime()) client.get_cpu_info() print(client.list_blocks()) print(str(client.db_read(1, 0, 100))) client.db_write(1, 0, bytearray(b"HELLO, SERVER!")) print(str(client.db_read(1, 0, 100))) client.disconnect() client.plc_stop() except RuntimeError as ex: print(ex)
from snap7.client import Client from snap7.util import * from snap7.snap7exceptions import Snap7Exception from snap7.snap7types import * from extras import * IP = '127.0.0.1' PORT = 8088 RACK = 0 SLOT = 0 client = Client() client.connect(IP, RACK, SLOT, PORT) with open('lecturas/db_small_int.txt', 'r') as f: layout = f.read() db_number = 0 all_data = client.db_get(db_number) db1 = DB_mixin( db_number, # the db we use all_data, # bytearray from the plc layout, # layout specification DB variable data 10, # size of the specification 17 is start 3, # number of row's / specifications ) [print(db) for db in db1] ''' with open('lecturas/marcas.txt', 'r') as f: layout = f.read() all_data = client.read_area(S7AreaMK, 0, 0, 10) db2 = DB(
class MyPlc: area = {'I': 0x81, 'Q': 0x82, 'M': 0x83, 'D': 0x84} szs = {'x': 1, 'X': 1, 'b': 1, 'B': 1, 'w': 2, 'W': 2, 'd': 4, 'D': 4} def __init__(self, ip='192.168.0.1'): self.ip = ip self.INByteArray = bytearray([0, 0]) self.MKByteArray = bytearray([0, 0]) self.threadStatus = False self.varsdict = {} self.threads = {} self.plc = PlcClient() self.subNodes = [] self.subNodesD = {} self.keysDict = {} self.inNodes = {} def get_db(self, server_id): self.db_server = Server.query.get(server_id) self.connections() def connections(self): self.opc_ns_uri = self.db_server.server_namespace self.ep_url = 'opc.tcp://' + self.db_server.server_endpoint_url self.opclient = Client(self.ep_url) try: self.plc.connect(self.ip, 0, 1) # pass except Exception: self.conn_stat = "Could not connect to PLC" else: self.conn_stat = "PLC Connected Successfully" self.opclient.connect() self.root = self.opclient.get_root_node() self.idx = self.opclient.get_namespace_index( self.db_server.server_namespace) self.set_tags(self.db_server.server_objects) for key, val in self.varsdict.items(): if re.search("^(M|m)([\d]+).[\d]*$", key) is not None: self.subNodes.append(val['obj']) self.subNodesD[key] = val else: self.inNodes[key] = val self.run_threads() handler = SubHandler(self) sub = self.opclient.create_subscription(200, handler) handle = sub.subscribe_data_change(self.subNodes) time.sleep(0.1) def set_tags(self, objs): for obj in objs: try: self.make_tag_dict(obj, obj.object_variables) except Exception: self.make_tags_dict(obj.object_variables) finally: for var in obj.object_variables: self.keysDict[var.variable_name] = var.variable_address def make_tag_dict(self, obj, allvars): for var in allvars: self.varsdict[var.variable_address] = { 'obj': self.root.get_child([ "0:Objects", "{}:{}".format(self.idx, obj.object_name), "{}:{}".format(self.idx, var.variable_name) ]), 'type': var.variable_type } def kill_threads(self): self.threadStatus = False def run_threads(self): self.threadStatus = True self.threads['update_server'] = threading.Thread( target=self.updateInputs) self.threads['update_server'].start() def getInputs(self): while self.threadStatus: self.INByteArray = self.plc.read_area(areas['PE'], 0, 0, 2) # self.INByteArray = bytearray([ randint(0,7), randint(0,7) ]) time.sleep(.1) # def get_bool(_bytearray, byte_index, bool_index): def updateInputs(self): while self.threadStatus: for key, val in self.inNodes.items(): self.update_server_vars(key) time.sleep(.01) def writetoPLC(self, value, node): key = self.keysDict[node.get_browse_name().to_string().split(':')[1]] self.write_to_plc(key, value) ''' Get Data from the PLC and Update OPC Server variables ''' def update_server_vars(self, addr_key): addr = addr_key.split('.') # Works with Boolean values from a Data Block if len(addr) == 3 and addr[0][0] == 'D': DBn = int(addr[0][2:]) DBt = addr[1][2] byt = int(addr[1][3:]) bit = int(addr[2]) reading = self.plc.read_area(MyPlc.area['D'], DBn, byt, szs[DBt]) if DBt == 'X' or DBt == 'x': self.varsdict[addr_key]['obj'].set_value( get_bool(reading, 0, bit)) # return get_bool( reading, 0, bit ) else: self.varsdict[addr_key]['obj'].set_value(reading) # return reading # Works with other data types from a Data Block elif len(addr) == 2 and addr[0][0] == 'D': DBn = int(addr[0][2:]) DBt = addr[1][2] byt = int(addr[1][3:]) reading = self.plc.read_area(MyPlc.area['D'], DBn, byt, szs[DBt]) if DBt == 'W' or DBt == 'w': self.varsdict[addr_key]['obj'].set_value(get_int(reading, 0)) # return get_int(reading,0) elif DBt == 'D' or DBt == 'd': self.varsdict[addr_key]['obj'].set_value(get_real(reading, 0)) # return get_real(reading,0) else: self.varsdict[addr_key]['obj'].set_value(reading) # Works with boolean values from Inputs,Merkels and Outputs elif len(addr) == 2: byt = int(addr[0][1:]) bit = int(addr[1]) reading = self.plc.read_area(MyPlc.area[addr[0][0]], 0, byt, 1) self.varsdict[addr_key]['obj'].set_value(get_bool(reading, 0, bit)) # return get_bool(reading,0,bit) # Works with other data types from Inputs,Merkels ot Outputs eg MW2 elif len(addr) == 1: byt = int(addr[0][2:]) typ = addr[0][1] reading = self.plc.read_area(MyPlc.area[addr[0][0]], 0, byt, 2) if typ == 'w' or typ == 'W': self.varsdict[addr_key]['obj'].set_value(get_int(reading, 0)) # return get_int(reading, 0) elif typ == 'd' or typ == 'D': self.varsdict[addr_key]['obj'].set_value(get_real(reading, 0)) # return get_real(reading, 0) else: self.varsdict[addr_key]['obj'].set_value(reading) # return reading ''' WRITE DATA TO PLC FROM SERVER ''' def write_to_plc(self, addr_key, value): addr = addr_key.split('.') print("New data change on {} : {}".format(addr_key, value)) # Works with Boolean values from a Data Block if len(addr) == 3 and addr[0][0] == 'D': DBn = int(addr[0][2:]) DBt = addr[1][2] byt = int(addr[1][3:]) bit = int(addr[2]) reading = self.plc.read_area(MyPlc.area['D'], DBn, byt, MyPlc.szs[DBt]) if DBt == 'X' or DBt == 'x': set_bool(reading, 0, bit, value) self.plc.write_area(MyPlc.area['D'], DBn, byt, reading) # Works with other data types from a Data Block elif len(addr) == 2 and addr[0][0] == 'D': DBn = int(addr[0][2:]) DBt = addr[1][2] byt = int(addr[1][3:]) reading = self.plc.read_area(MyPlc.area['D'], DBn, byt, MyPlc.szs[DBt]) if DBt == 'W' or DBt == 'w': set_int(reading, 0, value) elif DBt == 'D' or DBt == 'd': set_real(reading, 0, value) self.plc.write_area(MyPlc.area['D'], DBn, byt, reading) # Works with boolean values from Inputs,Merkels ot Outputs elif len(addr) == 2: byt = int(addr[0][1:]) bit = int(addr[1]) reading = self.plc.read_area(MyPlc.area[addr[0][0]], 0, byt, 1) set_bool(reading, 0, bit, value) self.plc.write_area(MyPlc.area[addr[0][0]], 0, byt, reading) # Works with other data types from Inputs,Merkels ot Outputs eg MW2 elif len(addr) == 1: byt = int(addr[0][2:]) typ = addr[0][1] reading = self.plc.read_area(MyPlc.area[addr[0][0]], 0, byt, 2) if typ == 'w' or typ == 'W': set_int(reading, 0, value) elif typ == 'd' or typ == 'D': set_real(reading, 0, value) else: set_data(value) self.plc.write_area(MyPlc.area[addr[0][0]], 0, byt, reading)
marca = DB_mixin(0, marca_data, layout_marca, LONGITUD_MARCAS, 1) indice = marca[0]['index'] - 1 INDEX[0] = indice _db = db[indice] _db.read(client) if INDEX[0] != INDEX[1] or INDEX[ 0] is None: # verifico si paso de indic para no repetir write_csv(_db.export()) INDEX[1] = INDEX[0] except Exception as e: logging.error(e) if __name__ == "__main__": client = Client() reconect(client) db_data = client.db_get(DB) marca_data = client.read_area(S7AreaMK, 0, 0, LONGITUD_MARCAS) db = DB_mixin(DB, db_data, layout, LONGITUD_STRUCT, LONGITUD_ARRAY) marca = DB_mixin(0, marca_data, layout_marca, LONGITUD_MARCAS, 1) #schedule.every(DELAY).seconds.do(main, client=client, db=db, marca=marca) while True: try: if not client.get_connected(): reconect(client) main(client=client, db=db)
def __init__(self, camera_number, config_file='config.yml') -> None: self.load_config(config_file) self.camera_number = camera_number self.client = Client()
def client(self) -> Client: plc: Client = Client() plc.connect(self.ip, self.rack, self.slot, self.port) return plc
except ImportError: import code def embed(): vars = globals() vars.update(locals()) shell = code.InteractiveConsole(vars) shell.interact() opc_url = "opc.tcp://localhost:4840/elevator/pid/" opc_client = Client( opc_url ) opc_uri = "http://thaintersect.com" updateThread = True global plc plc = SnapClient() def updates(): while True: # Set Speed Value on OPC Server lspd.set_value(get_real( plc.read_area(areas['MK'], 0, 40, 4), 0)) # MD4 direction = get_bool( plc.read_area( areas['MK'], 0, 20,1 ),0,1 ) # M20.1 goingup.set_value(direction) # if direction: # lspd.set_value(aspd.get_value() ) # else: # lspd.set_value( -aspd.get_value() ) # Set Distance variable in the PLC
from snap7.client import Client import struct plc = Client() plc.connect('192.168.14.100', 0, 1) data = plc.db_read('16', )
def __init__(self, ipaddr, name=None): self.ipaddr = ipaddress.IPv4Address(ipaddr) self.name = name self._port = 102 self._client = Client() self.SmartTags = SmartTags(self)