paulscherrerinstitute / pcaspy

Portable Channel Access Server in Python
BSD 3-Clause "New" or "Revised" License
32 stars 24 forks source link

Camonitor not working with pcaspy PVs #75

Closed MarcoMontevechi closed 2 years ago

MarcoMontevechi commented 2 years ago

Hello!

I am making a motors control IOC with pcaspy. The motor IOC has a Driver with the poll thread (as suggested here before) and it works fine to move the motors and get information. However, since there is no scan field defined, the camonitor command does not work properly: it does not show a PV value when it changes.

Example:

caget MOTOR:POS

5

camonitor MOTOR:POS (in another terminal)

MOTOR:POS 2022-04-02 13:59:47.914053 5

caput MOTOR:POS 1

Old : MOTOR:POS 5.0 New : MOTOR:POS 4.999282

(wait some time) caget MOTOR:POS

MOTOR:POS 0.999999

while the camonitor terminal never reacted. Is there a way to fix this?

MarcoMontevechi commented 2 years ago

Update: by looking at the source code, i figured calling the .scan() method directly inside the polling function (instead of defining the scan field inside the database) would solve my problem. It did. Will this work against me in the future? Is it a good idea?

xiaoqiangwang commented 2 years ago

The call to self.updatePVs() in the polling function shall publish the changes to camonitor clients.

MarcoMontevechi commented 2 years ago

Specifically in my case this didnt work because some PVs are used to take large amount of data from the controller and take too much time to update, compromising the other PVs. They are supposed to be processed only when the user invokes caget. But basically what i did was create a second self.updatePVs() method that updates only the PVs im interested in.

MarcoMontevechi commented 2 years ago

Okay, leaving another comment here because i think it might be useful for someone in the future. I had a list of PVs. Some of the PVs in this list needed to be updated but some couldnt be updated in the polling thread because they dealt with big strings and took a long time, freezing the update and consequently making camonitor basically useless for other PVs. Using Pv.scan() inside the polling thread was not good because scan() has a while True loop inside it, so it also freezed the polling thread. So i needed to select PV by PV to update them. The thing is: updateValue() almost always returned me KeyErrors even when i was sure that i was using the PV name.

It seems that creating the PVs with server.createPV(prefix, suffix) creates a PV with name prefix+suffix, but the part of the name that ends up in the manager.pvs dictionary is only the suffix... so we have a PV named prefix+suffix but which can only be referenced in the code by suffix.

So to adequately querty for the PVs names i had to do something similar to:

for k in pcaspy.driver.manager.pvs.values(): for obj in k.keys(): and then iterate trough all the pv names in k. I hope this might help someone.

xiaoqiangwang commented 2 years ago

I am thinking about this option: create a PV Refresh, when it is written to 1, launch a thread to poll those PVs with big string.

MarcoMontevechi commented 2 years ago

"I am thinking about this option: create a PV Refresh, when it is written to 1, launch a thread to poll those PVs with big string."

I implemented it and it works nicely!