epics-modules / opcua

EPICS Device Support for OPC UA
Other
18 stars 13 forks source link

Better support for Enums #158

Open dirk-zimoch opened 1 month ago

dirk-zimoch commented 1 month ago
ralphlange commented 1 month ago
  • An mbbi or mbbo Record connected to an enum should directly use the returned value as an index (i.e. the device support should return 2). At the moment, it is necessary to set ONVL=1, TWVL=2, etc.

Generally, that sounds reasonable. What if the number is out of range?

  • An mbbi, mbbo, bi or bo record with no state strings defined connected to an enum should automatically set the state strings to the enum strings from the OPC-UA server.

Then for OPC UA disconnect/reconnect do what? Erase the strings on disconnect? Overwrite on reconnect? Both? Neither? I'd rather have a link option to select that behavior explicitly. Could default to yes, but the behavior options need to be clear on what happens at disconnect/reconnect.

  • A stringin or stringout (or lsi or lso) record connected to an enum should show (and for output records accept) the enum strings from the OPC-UA server instead of the string representation of the index number.

A single string record should show all enum strings? How?

  • A waveform (or aai or aao) record with FTVL=STRING connected to an array of enums should show (and accept) the enum strings from the OPC-UA server.

Here that would work: show all strings in a single record. (Why would you do that? Well, why not.)

dirk-zimoch commented 1 month ago

What if the number is out of range?

the record should become INVALID.

Erase the strings on disconnect?

No.

Overwrite on reconnect?

Yes.

A single string record should show all enum strings? How?

No, it should show the current state. Now it shows the current state index number like "3". Same with STRING waveforms for arrays of Enums: Show the current states of the elements.

ralphlange commented 1 month ago

A single string record should show all enum strings? How?

No, it should show the current state. Now it shows the current state index number like "3".

Ah. "...should show (and for output records accept) the enum strings from the OPC-UA server..." That sounds like changing the conversion enum <-> string ??!

dirk-zimoch commented 1 month ago

changing the conversion enum <-> string

Exactly. Instead of converting the enum to a string showing the index number, it should show the state name. That would be much more useful.

tboegi commented 1 month ago
Overwrite on reconnect?

In case that an enum has less members/defintions when the PLC progam is changed, do not keep old definitions.

Erase all before overwriting - which is now a new writing.

ralphlange commented 1 month ago
Overwrite on reconnect?

In case that an enum has less members/defintions when the PLC progam is changed, do not keep old definitions.

Erase all before overwriting - which is now a new writing.

Yes, like that.

dirk-zimoch commented 1 month ago

Erase all before overwriting - which is now a new writing

Of course. Keeping old strings would not make sense. The whole set of strings belongs together and should be erased / replaced atomically upon (re-)connect.

dirk-zimoch commented 3 weeks ago

Progress report:

Someone wants to write tests?

ralphlange commented 3 weeks ago

@karlvestin started working on adding tests for structured data, which would leave the enum tests and the UASDK variant for me?

dirk-zimoch commented 3 weeks ago

I was actually thinking of implementing the UASDK support myself.

One more point do discuss: When converting OPC-UA Enums to/from numbers, should it use the index (as now) or rather the numerical enum value? I think the latter. Example: enum { tic = 10; tac = 20; toe = 30 }. Receiving index 1 => string = "tac", int = 20 (instead of 1)

ralphlange commented 3 weeks ago

By default: Enum value, clearly. Maybe, on demand, later... yet another option to return the index instead (??)

dirk-zimoch commented 3 weeks ago

Status update: UASDK Support works. CHAR arrays work (like long strings). I have changed the string->number conversion a bit while implementing this: A string that does not represent a number (and in case of enums not an enum choice) does not silently convert to 0 any longer but fails now. To be exact, the string has to start with a number (optionally after space), so that " 2 eggs" -> 2 but "one chicken" -> WRITE alarm. I still have to do the index <-> enum value translations in case the enum values are not simply 0,1,2,3,... But I currently have no test setup for that. I use uaservercpp which has only one enum with non-trivial values (Priority) but no example data of that type. I also have no test setup for arrays of enums. I still have to test enums embedded in structures.

ralphlange commented 3 weeks ago

Just for the record...

Recent Tech-Talk shows the situation I think we need to avoid: a device constantly changing enum choices, based on its operational state. https://epics.anl.gov/tech-talk/2024/msg00779.php

Obviously, that this is more an interface design question than a technical issue. Technically: If OPC UA allows servers to change enum choices during a session, we should eventually be able to handle it. Sigh.

dirk-zimoch commented 3 weeks ago

device constantly changing enum choices

That will only happen on (re-)connect (e.g. when the OPC-UA server is restarted). To be exact: during initialRead. Of course, there is some time after the ioc starts but before the connection is established, during which the records will have empty choice strings. I call db_post_events(prec, &prec->val, DBE_PROPERTY) when the enums change so that reasonably recent GUIs will know to update the string table. Also it is the choice of the IOC engineer: If the record has already strings defined (e.g. in the template) when the connection is established the first time, the driver will not change them.