Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read plc value depending on other value change #259

Closed
AndreSchm opened this issue Aug 17, 2021 · 3 comments
Closed

Read plc value depending on other value change #259

AndreSchm opened this issue Aug 17, 2021 · 3 comments

Comments

@AndreSchm
Copy link

I would like to get the current value of a REAL variable in dependence of an other BOOL variable using a OnChange notification:

@plc.notification(pyads.PLCTYPE_BOOL)
def callback(handle, name, timestamp, value):
    if value==True:
        print(f"handle: {handle}")
        print(f"name: {name}")
        print(f"timestamp: {timestamp}")
        print(f"value: {value}")
        print(plc.read_by_name(f"GVL_MyValues.MyRealValue", plc_datatype=pyads.PLCTYPE_REAL))```

Then I add this callback to my changing bool variable:

plc.add_device_notification(f'MAIN.MyBoolValue', 
                                        pyads.NotificationAttrib(sizeof(pyads.PLCTYPE_BOOL)),
                                        callback)

Everything except the MyRealValue is printed when MyBoolValue changes to True. Do I have to configure something else or does pyads not support read_by_name() (I also tried symbol.read()) within a notification callback?

I am using pyads 3.3.4 on a Windows 10 machine.

@chrisbeardy
Copy link
Collaborator

Hi there. The issue here is unfortunately you can not do another ads call (e.g. read_by_name) with the same plc object while within the callback function as the callback function happens in another thread. This normally results in an ads timeout issue.

You have a couple of options.

  1. I have not actually tried this, but it may work so let me know if you do try. you may be able to define a new connection within the callback function, e.g.
with pyads.Connection(plc.ams_netid, plc.ams_port) as plc2:
    print(plc2.read_by_name(...))
  1. set a flag / add to an event queue etc and process the event in a main loop. This is normally the approach I take when I develop applications using pyads and PyQT.

Hope this helps.

@AndreSchm
Copy link
Author

AndreSchm commented Aug 23, 2021

Thank you very much @chrisbeardy. The first option works fine.
Can you also please provide a small sample for the second option? Thanks a lot in advance.

I also found the symbol with auto_update=True within a loop as workaround:

symbol = plc.get_symbol("MAIN.MyBoolValue")
symbol.auto_update = True
while True:
    sleep(0.01)
    if symbol.value == True:
        print(f"{datetime.datetime.now()}")
        print(plc.read_by_name("GVL_MyValues.MyRealValue", plc_datatype=pyads.PLCTYPE_REAL))

But I guess the two options you provided are better suited.

@chrisbeardy
Copy link
Collaborator

The example you show is essentially option 2. You are setting a flag, in this case one created for you by the symbol class, and then checking that flag in a loop.

You could get more complicated using the queue feature etc. Search "communicating across threads in python" but it all depends what you are trying to do and how complex it is. If my option 1 works or your code works then great ha.

Since this is a know limitation and you have a solution,if you could kindly close the issue on GitHub that would be great. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants