And the mbbi record used in this demo:
1 record(mbbi, "status") {
2 field("VAL", 3)
3 field("ZRST", "Level0")
4 field("ONST", "Level1")
5 field("TWST", "Level2")
6 field("THST", "Level3")
7 field("PINI", "1")
8 }
On 2/19/19 9:25 AM, Tong Zhang wrote:
> mypv.get(as_string=True) returns the string value as expected. Please
> see the detailed constructed fully functional demo below:
>
> Script works as expected with mbbi record:
>
> 7 import epics
> 8 import time
> 9
> 10
> 11 pv_name = 'INVALID_PV_NAME'
> 12
> 13 def pv_with_callback(pv_name):
> 14 pv = epics.PV(pv_name)
> 15 time.sleep(2)
> 16 def on_value_changed(char_value, **kws):
> 17 print("Char Value: ", char_value)
> 18 pv.add_callback(on_value_changed)
> 19
> 20
> 21 pv_with_callback(pv_name)
> 22
> 23 time.sleep(2)
> 24 pv_name = 'status'
> 25
> 26 pv_with_callback(pv_name)
>
> If commented out line 15th, and run it again, the behavior is changed,
> only value is returned in the callback rather than expected char_value.
>
Slight aside: the value-change callback will be called with a fixed signature with PV name as the first argument, and keyword arguments for everything else, including `char_value`. So, that should be
def on_value_change(pvname, char_value='?', **kws):
print("Char Value ", pvname, char_value)
But I think that is not the real issue, and is not solved by adding a `time.sleep()`.
I do think that the issue there -- and probably why the initial call to you callback is not seeing the char_values -- is that the PV needs to connect to the Control Values for the PV. That takes a small (but non-zero) amount of time. You should not need to wait 2 seconds, but waiting 0.01 seconds might help.
So, with no wait at alil, it seems sort of normal to me that the enum strings might not be **immediately available** upon creating a PV. It should show up very soon, but that initial call of the callback might not yet have the control values like enumeration strings.
There are a few things you could do. First, you could use the "control data type" as with:
pv = epics.PV(pv_name, form='ctrl')
pv.add_callback(on_value_change)
(the default value for "form" is "time" to give the Time-Status-Severity data type) or you could force retrieving the control types:
pv = epics.PV(pv_name)
pv.get_ctrlvars()
pv.add_callback(on_value_change)
You can also wait a short amount of time -- you do not need to wait 2 seconds, but waiting 0.01 seconds might help:
pv = epics.PV(pv_name)
time.sleep(0.01)
pv.add_callback(on_value_change)
If you're connecting to many PVs, I would suggest creating many of the PVs, then adding callbacks to all the PVs That approach allows all the connections (including fetching the control values) to be completed.
Hope that helps,
--Matt