gijzelaerr / python-snap7

A Python wrapper for the snap7 PLC communication library
http://python-snap7.readthedocs.org/
MIT License
643 stars 246 forks source link

b' ISO : An error occurred during recv TCP : Connection timed out' #387

Closed Momoben3434 closed 1 year ago

Momoben3434 commented 1 year ago

HI ALL, Im using a Pi4 with snap7 python to read data from plc cyclicly.

I encountered this issue while i'm reading constantly values of the PLC in every 0.65 sec then doing some calculations. Im a begginner on python and i would like to have some support understanding the error or guide me with documentations, examples. When the error occur i lose communication with PLC and i have to run py again.

im attaching the code of the app.

"""

"""

import snap7 from snap7 import types from snap7.types import WordLen, S7Object, param_types from snap7.common import ipv4, check_error, load_library from snap7.util import* import tkinter.filedialog from time import sleep import tkinter import time from datetime import datetime from pywhatkit import send_mail from credential import google_p from snap7.exceptions import Snap7Exception import ctypes import gc import logging import struct import time import unittest import platform from datetime import datetime, timedelta, date from multiprocessing import Process from unittest import mock

import snap7 from snap7 import util from snap7.common import check_error from snap7.server import mainloop from snap7.types import S7AreaDB, S7DataItem, S7SZL, S7SZLList, buffer_type, buffer_size, S7Object, Areas, WordLen

Snap 7 functions parameters

db_number = 127 start_offset = 4004 bit_offset = 1 value = 1 # 1 = true | 0 = false start_address = 13024 # starting address length = 4 # double word

variable init

sum = 0.0 test_completed = False count = 0 hold_1 = 0 results_received = False seconds = 0.0 volume_1 = 0.0 volume = 0.0 chassis_nr = '' connect = False

call snap7 client function

plc = snap7.client.Client(lib_location='/usr/local/lib/libsnap7.so')

IP address, rack, slot (from HW settings)

plc.connect('10.19.123.66', 0, 1)

Get plc is connected true or flase

plc_connected = plc.get_connected()

read plc state run/stop/error

state = plc.get_cpu_state()

print plc state

print(f'State :{state}')

def test_wait_as_completion_timeouted(self, timeout=0, tries=500):

Cli_WaitAsCompletion

    # prepare Server
    area = Areas.DB
    dbnumber = 1
    size = 1
    start = 1
    data = bytearray(size)
    wordlen, data = self.client._prepare_as_read_area(area, size)
    pdata = ctypes.byref(data)
    self.client.write_area(area, dbnumber, start, bytearray(data))
    # start as_request and wait for zero seconds to try trigger timeout
    for i in range(tries):
        self.client.as_read_area(area, dbnumber, start, size, wordlen, pdata)
        res = None
        try:
            res = self.client.wait_as_completion(timeout)
            check_error(res)
        except RuntimeError as s7_err:
            if not s7_err.args[0] == b'CLI : Job Timeout':
                self.fail(f"While waiting another error appeared: {s7_err}")
            # Wait for a thread to finish
            time.sleep(0.1)
            return
        except BaseException:
            self.fail(f"While waiting another error appeared:>>>>>>>> {res}")

    self.fail(f"After {tries} tries, no timout could be envoked by snap7. Either tests are passing to fast or"
              f"a problem is existing in the method. Fail test.")

def test_check_as_completion(self, timeout=5):

Cli_CheckAsCompletion

    check_status = ctypes.c_int(-1)
    pending_checked = False
    # preparing Server values
    data = bytearray(b'\x01\xFF')
    size = len(data)
    area = Areas.DB
    db = 1
    start = 1
    self.client.write_area(area, db, start, data)

    # start as_request and test
    wordlen, cdata = self.client._prepare_as_read_area(area, size)
    pcdata = ctypes.byref(cdata)
    self.client.as_read_area(area, db, start, size, wordlen, pcdata)
    for _ in range(10):
        self.client.check_as_completion(ctypes.byref(check_status))
        if check_status.value == 0:
            self.assertEqual(data, bytearray(cdata))
            break
        pending_checked = True
        time.sleep(1)
    else:
        self.fail(f"TimeoutError - Process pends for more than {timeout} seconds")
    if pending_checked is False:
        logging.warning("Pending was never reached, because Server was to fast,"
                        " but request to server was successfull.")

def readBool(db_number, start_offset, bit_offset): reading = plc.db_read(db_number, start_offset, 1) a = snap7.util.get_bool(reading, 0, bit_offset)

print('DB Number: ' + str(db_number) + ' Bit: ' + str(start_offset) + '.' + str(bit_offset) + ' Value: ' + str(a))

        return str(a)

def readMemory(start_address,length):

        reading = plc.read_area(snap7.types.Areas.MK, 0, start_address, length)
        value = struct.unpack('>f', reading)  # big-endian
        #print('Start Address : ' + str(start_address) + ' Value: ' + str(value))
        #print('Value: ' + str(value))

        return (value)

def writeMemory(start_address,length,value): plc.mb_write(start_address, length, bytearray(struct.pack('>f', value))) # big-endian plc.disconnect() print('Volume to PLC:' + str(value))

def append_new_line(file_name, text_to_append): """Append given text as a new line at the end of file"""

Open the file in append & read mode ('a+')

with open(file_name, "a+") as file_object:
    # Move read cursor to the start of file.
    file_object.seek(0)
    # If file is not empty then append '\n'
    data = file_object.read(100)
    if len(data) > 0:
        file_object.write("\n")
    # Append text at the end of file
    file_object.write(text_to_append)

def tic(): global _start_time _start_time = time.time()

def tac(): t_sec = round(time.time() - _start_time) (t_min, t_sec) = divmod(t_sec,60) (t_hour,t_min) = divmod(t_min,60) print('Time passed: {}hour:{}min:{}sec'.format(t_hour,t_min,t_sec))

def sendmail(message_to_send):

send_mail (
    email_sender = "zone4.primer.reply@gmail.com",
    email_receiver = ("mourad.benyoucef@magna.com","nathan.ramsahai@magna.com"),
    message = message_to_send ,
    password = google_p['password'],
    subject = "Alert ! Primer Zone 4 - Volume is too low !!"
           )
print("Mail sent")

def disconnect(self) -> int: """Disconnect a client. Returns: Error code from snap7 library. """ logger.info("disconnecting snap7 client") result = self.library.Cli_Disconnect(self.pointer) check_error(result, context="client") return result

Write results to a file.

file_name = tkinter.filedialog.askopenfilename()

Write reject results to a file

reject_filename = tkinter.filedialog.askopenfilename()

while(True):

#Check the plc is connected 
#if plc_connected :

if not plc.get_connected():
    try:

        plc = snap7.client.Client(lib_location='/usr/local/lib/libsnap7.so')
        plc.connect('10.19.123.66', 0, 1)             

    except Snap7Exception as e:
        logger.error("warning in PLC connection >>{}".format(e))
        connect = False
        continue

else:

        #get string test
        data = plc.db_read(db_number=127, start=4014, size=8)

        # read the trigger from PLC
        read_start_req = readBool(127,4004,1)

        # time stamp 
        now = datetime.now()

        if read_start_req == 'True':

            results_received = False

            # readings reading 
            for x in readMemory(13024,4):
                time.sleep(0.65)
                count = count + 1
                my_results = x
                sum = sum + my_results
                print(count)
                print('Readings :' + str(my_results) )
                print('sum:' + str(sum))               

        else:

            # Sum of the readings 
            if count > 0 and not results_received:
                # compensation factor.12.522 ml

                # Volume calculation
                volume = sum /60

                #Dentsity beta 5404 is 0.9
                weight = volume * 0.90

                #results time stamps 
                timestamp = datetime.timestamp(now)
                dt_object = datetime.fromtimestamp(timestamp)

                if str(snap7.util.get_string(data, 0)) == '':
                    chassis_nr = 'NO RFID DATA'
                else:
                    chassis_nr = str(snap7.util.get_string(data, 0))

                    #Display results to the user 
                print('Job Number:'+" "+ chassis_nr +" "+','+ 'Volume Dispensed is :'+" "+ str(volume)+ " " + '(ml)'+" " + '/' + str(weight) +'(g)')                    
                print(str(sum))
                contents = ("Job Number:"+"\n"+ chassis_nr + " " + "\n" + "Volume Dispensed:" + "\n" + str(volume)+" "+ '(ml)' + "\n" + "Time Stamp :" "\n" + str(dt_object))

                #Update the file with the results (append)
                append_new_line(file_name, contents)

                #Write the volume to te PLC
                writeMemory(4010,4,volume)

                #send mail to process team 
                if volume <= 0.3 or volume == 0.0:
                    sendmail(contents)
                    #Update the file with the results (append )
                    append_new_line(reject_filename, contents)                               

                results_received = True

                # Close connection 
                plc.disconnect()
                time.sleep(10)
                print('plc connect ', connect)

                #Init the variables 
                count = 0
                volume = 0.0
                volume_1 = 0.0
                sum = 0.0               

            else :

                hold_1 = hold_1 + 1

                if hold_1 < 1:

                        print('...')
                        results_received = False

Error : b' ISO : An error occurred during recv TCP : Connection timed out' Traceback (most recent call last): File "/home/momo3434/Desktop/PyProject/primer/python/snap7_/zone4_primer_1.py", line 231, in read_startreq = readBool(127,4004,1) File "/home/momo3434/Desktop/PyProject/primer/python/snap7/zone4_primer_1.py", line 136, in readBool reading = plc.db_read(db_number, start_offset, 1) File "/usr/local/lib/python3.9/dist-packages/snap7/client.py", line 226, in db_read check_error(result, context="client") File "/usr/local/lib/python3.9/dist-packages/snap7/common.py", line 89, in check_error raise RuntimeError(error) RuntimeError: b' ISO : An error occurred during recv TCP : Connection timed out'