kasemir / org.csstudio.display.builder

Update of org.csstudio.opibuilder.*
Eclipse Public License 1.0
2 stars 10 forks source link

EPICS Channel Access only supports 16 enum states. Display Builder displays .STAT fields with value == 17 as '17' instead of 'UDF' #450

Closed claudio-rosati closed 6 years ago

claudio-rosati commented 6 years ago

Display Builder Text Entry and Text Update widgets displays '17' instead of 'UDF' for a .STAT field valued to 17.

kasemir commented 6 years ago

That's a limitation in Channel Access. Try 'caget -d CTRL_ENUM' with that channel: Channel Access only provides 16 enum strings. If you have more, you cannot read them.

claudio-rosati commented 6 years ago

Thank you Kay for the explanation.

kasemir commented 6 years ago

For the record, here's the detail:

$ caget -d CTRL_ENUM TryAnyRecordYouWant.STAT
TryAnyRecordYouWant.STAT
    Native data type: DBF_ENUM
    Request type:     DBR_CTRL_ENUM
    Element count:    1
    Value:            NO_ALARM
    Status:           NO_ALARM
    Severity:         NO_ALARM
    Enums:            (16)
                      [ 0] NO_ALARM
                      [ 1] READ
                      [ 2] WRITE
                      [ 3] HIHI
                      [ 4] HIGH
                      [ 5] LOLO
                      [ 6] LOW
                      [ 7] STATE
                      [ 8] COS
                      [ 9] COMM
                      [10] TIMEOUT
                      [11] HWLIMIT
                      [12] CALC
                      [13] SCAN
                      [14] LINK
                      [15] SOFT

The underlying reason is in EPICS base/include/db_access.h:

#define MAX_ENUM_STATES         16      
...
/* structure for a control enumeration field */
struct dbr_ctrl_enum{
        dbr_short_t     status;                 /* status of value */
        dbr_short_t     severity;               /* severity of alarm */
        dbr_short_t     no_str;                 /* number of strings */
        char    strs[MAX_ENUM_STATES][MAX_ENUM_STRING_SIZE];
                                        /* state strings */
        dbr_enum_t      value;          /* current value */
};

Channel Access cannot get more than 16 enum states. This includes the built-in enums like the enum epicsAlarmCondition which has more than 20 states. No problem for code that uses the enum as a number. Code that requests the value as a string will get the enum index as a string since we don't know the label.

tboegi commented 6 years ago

Thanks Kay.

This is what I get via caget ("Value: 17; Status: UDF").

caget -d CTRL_ENUM IOC:m1.STAT IOC:m1.STAT Native data type: DBF_ENUM Request type: DBR_CTRL_ENUM Element count: 1 Value: Illegal Value (17) Status: UDF Severity: INVALID Enums: (16) [ 0] NO_ALARM [ 1] READ [ 2] WRITE [ 3] HIHI [ 4] HIGH [ 5] LOLO [ 6] LOW [ 7] STATE [ 8] COS [ 9] COMM [10] TIMEOUT [11] HWLIMIT [12] CALC [13] SCAN [14] LINK [15] SOFT

tboegi commented 6 years ago

This is what caget is doing (according to wireshark & ca.lua): Command: Read Notify (0x000f) Payload Size: 0 DBR Type: TIME_STRING (14) Data Count: 1 Operation ID: 1 Server Channel ID: 71

And then the IOC answers: Command: Read Notify (0x000f) Payload Size: 56 DBR Type: TIME_STRING (14) Data Count: 1 Operation ID: 1 Status: ECA_NORMAL (0x00000001) Status: 17 Severity: 3 Timestamp: Mon 01 Jan 1990 01:00:00 AM CET Value: UDF

kasemir commented 6 years ago

For efficiency reasons, higher level clients like CS-Studio, EDM, ... create one connection to each PV, fetch the metadata once, and the subscribe to updates for the native type of the value.

So for an enum, we fetch the labels once (where Channel Access is limited to 16 options), and then subscribe to the native type (enum == index of the current option). No matter if that value is then used in a plot, textupdate, probe, PV tree, ... it's just one 'channel'.

Yes, you could create a separate channel each time you need access to a PV, and you could push the data type conversion to the CA server side: TextUpdate creates a channel where it asks for the TIME_STRING, Data Browser asks for the channel as a TIME_DOUBLE, Combo asks for the channel as a TIME_ENUM, ...

==> Yes, textupdate would now show "UDF" because it fetched the enum option 17 as a string. (See output of your caget that fetches data as STRING)

But Combo would still show "<17>" because it fetched the enum as an enum (See output of your caget which requests the ENUM)/ And it would create many channels, increase network traffic and CPU load on both IOC and client.

kasemir commented 6 years ago

Here's what you get from EDM: edm

It also connects to the channel just once. For the selection widget it sees the first 16 options. For a text update, it doesn't even show "<17>" to indicate that it's the unknown option index 17, you just see "". That happens to be similar to the actual option 17=UDF, but you would also see "" for STAT option 18 == Disable, option 19=Simm, option 20=ReadAccess, ..

For what it's worth, directly reading the "xxx.STAT" field is a border case that you might want to reconsider. You cannot depend on having a record with a "xxx.STAT" field at the CA server end. These days you might be talking to a pcaspy-based CA server, which will support all the DBR_* requests for channel "xxx" but there is no "xxx.STAT".

If you simply connect to the "xxx" channel, the subscription to DBRSTS will read the status and severity. That way the complete list of status enums is known, and the VType Alarm will give that to the widget. So if you need a channels alarm severity, status, time, units, limits, .. instead of creating a separate channel for SEVR, STAT, TIME, EGU, HOPR, HIHI, ... it's better to just connect to "xxx" and then you can get all the metadata from the VType.

claudio-rosati commented 6 years ago

For efficiency reasons, higher level clients like CS-Studio, EDM, ... create one connection to each PV, fetch the metadata once, and the subscribe to updates for the native type of the value.

I think this is the most important statement: understanding how currently the client works.

@tboegi as I have already said in the ESS JIRA issue you opened, in you specific application probably it is better to substitute the Text Input/Text Update widget wit a Label one a a rule that, triggered by the .STAT field will display all the strings defined in the EPICS specification for the STAT field. Maybe it is not the most elegant solution but it will give you what you want quickly.

@kasemir do you know the current situation for the PV Access? Enumerations are still bound to a nibble?

kasemir commented 6 years ago

The PVAccess situation is better. You get all the options:

pva

So the implementation of edm, medm, BOY, Display Builder, .. has been correct for decades. You're welcome to work on a fix for Channel Access, but that would require an update to the protocol. With PVAccess, you're fine.

Still, consider connecting to just "xxx" instead of "xxx.STAT" because that supports any CA server, not limited to IOCs.

claudio-rosati commented 6 years ago

I understand your advice, but I think @tboegi can't do that in its very specific motor control page. I'll see what can be dome when I'll try to convert it to Display Builder.

Meanwhile, if I've understood correctly, in Display Builder I can see "UDF" in a Text Update widget if the same PV is served via pva instead of ca. I've understood correctly?

tboegi commented 6 years ago

Thanks for all the digging, guys. My question was to ask if the client be improved to work like caget, especially as we run IOC's which seem to have enough CPU power to do this. Now I understand the comment "For efficiency reasons" much better. It feels not reasonable to ask for a change in CSS, when we know that using pvaccess will solve the problem.