Skip to content

Registering multiple notifications on the AdsTestServer #471

@TurboThommy

Description

@TurboThommy

Hello,

I tried to use the AdsTestServer with AdvancedHandler to mock the behaviour of a PLC.
Everything worked great up until the point where I tried to create multiple device notifications:

Code
  from ctypes import sizeof
  import struct
  import pyads
  from pyads.testserver import AdsTestServer, AdvancedHandler, PLCVariable
  from pyads import constants
  
  from time import sleep
  
  
  def main():
      handler = AdvancedHandler()
      test_server = AdsTestServer(handler=handler)
  
  
      test1 = PLCVariable(
          'Test1',
          value=0,
          ads_type=constants.ADST_UINT32,
          symbol_type='DWORD',
          index_group=61445,
          index_offset=10000
      )
      handler.add_variable(test1)
  
  
      test2 = PLCVariable(
          'Test2',
          value=0,
          ads_type=constants.ADST_UINT32,
          symbol_type='DWORD',
          index_group=61445,
          index_offset=10001
      )
      handler.add_variable(test2)
  
  
      sleep(1)
  
  
      test_server.start()
      plc = pyads.Connection('127.0.0.1.1.1')
  
  
      def callback1(notification, data):
          try:
              _, _, value = plc.parse_notification(
                  notification=notification,
                  plc_datatype=pyads.PLCTYPE_DWORD
              )
              print(f'Callback 1: {data}: {value}')
          except:
              print('Error in callback1.')
  
  
      def callback2(notification, data):
          try:
              _, _, value = plc.parse_notification(
                  notification=notification,
                  plc_datatype=pyads.PLCTYPE_DWORD
              )
              print(f'Callback 2: {data}: {value}')
          except:
              print('Error in callback2.')
  
  
      with plc:
          symbol1 = handler.get_variable_by_name('Test1')
          symbol2 = handler.get_variable_by_name('Test2')
  
          attr = pyads.NotificationAttrib(sizeof(pyads.PLCTYPE_DWORD))
          plc.add_device_notification(
              data='Test1',
              attr=attr,
              callback=callback1
          )
  
          attr = pyads.NotificationAttrib(sizeof(pyads.PLCTYPE_DWORD))
          plc.add_device_notification(
              data='Test2',
              attr=attr,
              callback=callback2
          )
  
          symbol1.write(struct.pack('<I', 1))
          symbol2.write(struct.pack('<I', 10))
  
      sleep(1)
      test_server.stop()
      sleep(1)
  
  
  if __name__ == "__main__":
      main()

I expected following output:

Expected Output
2025-07-10T17:36:32+0200 Info: Connected to 127.0.0.1
Callback 1: Test1: 1
Callback 2: Test2: 10
2025-07-10T17:36:32+0200 Info: connection closed by remote

But instead I got:

Actual Output
2025-07-10T17:36:32+0200 Info: Connected to 127.0.0.1
Callback 2: Test2: 1
Callback 2: Test2: 10
2025-07-10T17:36:32+0200 Info: connection closed by remote

To me it seems like only the callback registered last is used. Unfortunately I don't have real hardware at hand right now to test if this is only the case for the test server.

The application is run on Ubuntu using the WSL in case that makes any difference.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions