stlehmann / pyads

Python wrapper for TwinCAT ADS
MIT License
254 stars 94 forks source link

ADSError: timeout elapsed (1861) @ plc.del_device_notification #234

Closed bschmucker closed 3 years ago

bschmucker commented 3 years ago

Dear all,

I get the following error when calling _plc.del_devicenotification(*handles).

Exception in thread Thread-1: Traceback (most recent call last): File "C:\ProgramData\Anaconda3\envs\CLM_test\lib\threading.py", line 916, in _bootstrap_inner self.run() File "C:\ProgramData\Anaconda3\envs\CLM_test\lib\threading.py", line 864, in run self._target(*self._args, **self._kwargs) File "c:/temp/Workspaces/clm_demo_application/communication_with_Siemens_controller/DAQ_application/DAQ_GUI/clm_tc_daq_gui.py", line 210, in producer self.plc.del_device_notification(*handles) File "C:\ProgramData\Anaconda3\envs\CLM_test\lib\site-packages\pyads\ads.py", line 1179, in del_device_notification self._port, self._adr, notification_handle, user_handle File "C:\ProgramData\Anaconda3\envs\CLM_test\lib\site-packages\pyads\pyads_ex.py", line 1189, in adsSyncDelDeviceNotificationReqEx raise ADSError(err_code) pyads.pyads_ex.ADSError: ADSError: timeout elapsed (1861).

In the following you can find the code section, where this Timeout is thrown. << beginning of code section

   def producer(self): 
        self.PLC_LOC = 'GVL_DataOutput'
        self.STRUCTURE_NAME = 'strTimeSeries_OS10_5_Output'
        self.PY_DUT_TYPE = PY_DUT_TC_CLM40_munich_10_OS
        self.PYADS_STRUCT_NAME = self.PLC_LOC + '.' + self.STRUCTURE_NAME
        self.PYADS_STRUCT_SIZE_INT = pyads.size_of_structure(self.PY_DUT_TYPE)
        self.PYADS_STRUCT_SIZE = pyads.ads.c_ubyte*self.PYADS_STRUCT_SIZE_INT
    @self.plc.notification(self.PYADS_STRUCT_SIZE)
    def callback(handle, name, timestamp, value):
        print(
            '{1}: received new notification for variable "{0}"'
            .format(name, timestamp)
        )
        self.q.put(pyads.dict_from_bytes(value, self.PY_DUT_TYPE))

    notAttrib = pyads.NotificationAttrib(self.PYADS_STRUCT_SIZE_INT)
    handles = self.plc.add_device_notification(self.PYADS_STRUCT_NAME, notAttrib, callback)

    while True:
        if self.acquire.is_set():
            time.sleep(0.0001)
        else:
            if self.notification_delete == 0:
                print("delete handles: ", self.notification_delete)
                self.plc.del_device_notification(*handles)
                time.sleep(10)
                self.notification_delete = self.notification_delete + 1
            else:
                break

>> ending of code section

After this Timeout the ADS communication still works fine. I use "Write by name" method subsequently and the Value is changed in Twincat.

System description:

I would appreciate your help! Is this an API issue or is it my code which causes the problem? Do you have any suggestion for solving this issue?

Is it possible that this is a multi threading issue? When I debug my code, this Timeout is not raised. Therefore, it is hard to understand the issue.

Thank you very much!

chrisbeardy commented 3 years ago

Hi, I've not had a chance to fully review and test this. But I suspect this is a multthreading issue, especially as you can't replicate during debug. In my experience when using another thread I always create a plc connection per thread. So that any interactions to the PLC from the main thread do not interfere with the other thread. There may be a case where ADS is trying to delete the notification and do something else.

You also get timeout issues when trying to make an an ads call from within a callback function but I think that is a separate issue.

bschmucker commented 3 years ago

Thank you very much for your answer and the hint to create a seperate plc connection per thread. I do agree with your pereception that this is a multi threading issue, because I was able solve the problem by a different order when stopping the various threads. But I think a more robust way is to use the separate plc connections. Thanks!