1818import org .epics .vtype .Alarm ;
1919import org .epics .vtype .AlarmSeverity ;
2020import org .epics .vtype .AlarmStatus ;
21+ import org .epics .vtype .Display ;
22+ import org .epics .vtype .DisplayProvider ;
2123import org .epics .vtype .Time ;
2224import org .epics .vtype .VByteArray ;
2325import org .epics .vtype .VEnum ;
3032import org .phoebus .core .vtypes .VTypeHelper ;
3133import org .phoebus .pv .PV ;
3234import org .phoebus .pv .PVPool ;
35+ import org .phoebus .pv .PVPool .TypedName ;
3336
3437import io .reactivex .rxjava3 .disposables .Disposable ;
3538
@@ -51,7 +54,8 @@ public class PVTableItem
5154 private volatile VType value ;
5255
5356 /** Value of the PV's description */
54- private volatile String desc_value = "" ;
57+ private volatile String desc_value = null ;
58+ private volatile String desc_name = "" ;
5559
5660 /** Saved (snapshot) value */
5761 private volatile Optional <SavedValue > saved = Optional .empty ();
@@ -77,6 +81,9 @@ public class PVTableItem
7781
7882 /** Listener to description PV */
7983 private volatile Disposable desc_flow ;
84+
85+ private static final String DESC_FIELD = "DESC" ;
86+ private static final String DOT = "." ;
8087
8188 /** Initialize
8289 *
@@ -122,16 +129,24 @@ private void createPVs(final String name)
122129 updateValue (null );
123130 return ;
124131 }
132+ PV new_pv = null ;
125133 try
126134 {
127135 updateValue (VString .of ("" , Alarm .disconnected (), Time .now ()));
128- final PV new_pv = PVPool .getPV (name );
136+ new_pv = PVPool .getPV (name );
129137 value_flow = new_pv .onValueEvent ()
130138 .throttleLatest (Settings .max_update_period_ms , TimeUnit .MILLISECONDS )
131139 .subscribe (this ::updateValue );
132140 permission_flow = new_pv .onAccessRightsEvent ()
133141 .subscribe (writable -> listener .tableItemChanged (PVTableItem .this ));
134142 pv .set (new_pv );
143+ // read the value for getting description
144+ if (new_pv != null ) {
145+ VType newVal = new_pv .read ();
146+ if (newVal != null ){
147+ updateValue (newVal );
148+ }
149+ }
135150 }
136151 catch (Exception ex )
137152 {
@@ -141,19 +156,25 @@ private void createPVs(final String name)
141156 Time .now ()));
142157 }
143158
144- // For CA PVs, check the .DESC field
145- // Hardcoded knowledge to avoid non-record PVs.
146- if (Settings .show_description &&
147- ! (name .startsWith ("sim:" ) ||
148- name .startsWith ("loc:" )))
149- {
150- // Determine DESC field.
151- // If name already includes a field,
152- // replace it with DESC field.
153- final int sep = name .lastIndexOf ('.' );
154- final String desc_name = sep >= 0
155- ? name .substring (0 , sep ) + ".DESC"
156- : name + ".DESC" ;
159+ // First try to get description from value or pv
160+ updateDescription ();
161+ // If still no description found and channel access source
162+ final TypedName type_name = TypedName .analyze (name );
163+ String dataType = type_name != null ? type_name .type : null ;
164+ boolean channelAccess = dataType .equals ("ca" );
165+ if (Settings .show_description && desc_value == null && channelAccess ) {
166+ // For CA PVs, check the .DESC field
167+ // Hardcoded knowledge to avoid non-record PVs.
168+ // First get default datasource
169+ desc_name = name + DOT + DESC_FIELD ; // by default add .DESC
170+ if (!name .endsWith (DOT + DESC_FIELD ) && name .contains (DOT )) {
171+ final int sep = name .lastIndexOf ('.' );
172+ String fieldVal = name .substring (sep + 1 );
173+ // then replace by .DESC
174+ // Determine DESC field include dot in case of variable name such as variableEGUName
175+ desc_name = name .replace (DOT + fieldVal , DOT + DESC_FIELD );
176+ }
177+
157178 try
158179 {
159180 final PV new_desc_pv = PVPool .getPV (desc_name );
@@ -175,6 +196,27 @@ private void createPVs(final String name)
175196 }
176197 }
177198 }
199+
200+ private void updateDescription () {
201+ if (desc_value == null ) {
202+ //update description from value or pv
203+ VType currentValue = getValue ();
204+ if (currentValue != null ) {
205+ PV thePV = pv .get ();
206+ // DisplayProvider is an optional interface for VType values,
207+ // not PVs, but the custum datasource as Muscade happens to implement
208+ // DisplayProvider for enum and bool PVs, so check for that here
209+ Display display = thePV instanceof DisplayProvider ? ((DisplayProvider ) thePV ).getDisplay () : null ;
210+ display = display == null && currentValue instanceof DisplayProvider ? ((DisplayProvider ) currentValue ).getDisplay (): display ;
211+ if (display != null ) {
212+ String description = display .getDescription ();
213+ desc_value = description != null ? description : null ;
214+ desc_name = desc_value != null ? "Description of " + name + " PV" : "no description" ;
215+ desc_flow = value_flow ;
216+ }
217+ }
218+ }
219+ }
178220
179221 /** @return <code>true</code> if item is selected to be restored */
180222 public boolean isSelected ()
@@ -240,9 +282,13 @@ public VType getValue()
240282 }
241283
242284 /** @return Description */
243- public String getDescription ()
244- {
245- return desc_value ;
285+ public String getDescription () {
286+ return desc_value == null ? "" : desc_value ;
287+ }
288+
289+ /** @return description pv name **/
290+ public String getDescriptionName () {
291+ return desc_name ;
246292 }
247293
248294 /** @return Enum options for current value, <code>null</code> if not enumerated */
@@ -285,14 +331,17 @@ public void setValue(String new_value)
285331 throw new Exception ("Not connected" );
286332
287333 final VType pv_type = the_pv .read ();
288- if (pv_type instanceof VNumber )
289- {
290- if (Settings .show_units )
291- { // Strip units so that only the number gets written
292- final String units = ((VNumber )pv_type ).getDisplay ().getUnit ();
293- if (units .length () > 0 && new_value .endsWith (units ))
334+ Display display = the_pv instanceof DisplayProvider ? ((DisplayProvider ) the_pv ).getDisplay () : null ;
335+ display = display == null && pv_type instanceof DisplayProvider ? ((DisplayProvider ) pv_type ).getDisplay ():null ;
336+
337+ if (display != null && Settings .show_units ) {
338+ // Strip units so that only the number gets written
339+ final String units = display .getUnit ();
340+ if (units .length () > 0 && new_value .endsWith (units ))
294341 new_value = new_value .substring (0 , new_value .length () - units .length ()).trim ();
295342 }
343+ if (pv_type instanceof VNumber )
344+ {
296345 the_pv .write (Double .parseDouble (new_value ));
297346 }
298347 else if (pv_type instanceof VEnum )
0 commit comments