diff --git a/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/WidgetRuntime.java b/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/WidgetRuntime.java index 8cfed3cbbf..b1767f8783 100644 --- a/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/WidgetRuntime.java +++ b/app/display/runtime/src/main/java/org/csstudio/display/builder/runtime/WidgetRuntime.java @@ -26,6 +26,7 @@ import org.epics.vtype.VType; import org.phoebus.framework.macros.MacroHandler; import org.phoebus.framework.macros.MacroValueProvider; +import org.phoebus.pv.PVPool.TypedName; import java.util.ArrayList; import java.util.Collection; @@ -235,7 +236,9 @@ public void start() { final String pv_name = ((WritePVAction) action).getPV(); try { final String expanded = MacroHandler.replace(widget.getMacrosOrProperties(), pv_name); - final RuntimePV pv = PVFactory.getPV(expanded); + // Manage default datasource if not ca + final TypedName type_name = TypedName.analyze(expanded); + final RuntimePV pv = PVFactory.getPV(type_name.toString()); action_pvs.add(pv); addPV(pv, true); } catch (Exception ex) { @@ -395,8 +398,12 @@ public void writePrimaryPV(final Object value) { public void writePV(final String pv_name, final Object value) throws Exception { final String expanded = MacroHandler.replace(widget.getMacrosOrProperties(), pv_name); String name_to_check = expanded; + // Check for default datasource to manage custom datasource + final TypedName type_name = TypedName.analyze(name_to_check); + name_to_check = type_name != null ? type_name.toString() : name_to_check; + String dataType = type_name != null ? type_name.type : null; // For local PV, - if (name_to_check.startsWith("loc://")) { + if (dataType != null && dataType.equals("loc")) { // strip optional data type ... int sep = name_to_check.indexOf('<'); if (sep > 0) diff --git a/app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/WidgetRuntimeTest.java b/app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/WidgetRuntimeTest.java new file mode 100644 index 0000000000..7c7b0b7025 --- /dev/null +++ b/app/display/runtime/src/test/java/org/csstudio/display/builder/runtime/test/WidgetRuntimeTest.java @@ -0,0 +1,79 @@ +package org.csstudio.display.builder.runtime.test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.csstudio.display.actions.WritePVAction; +import org.csstudio.display.builder.model.properties.ActionInfos; +import org.csstudio.display.builder.model.properties.CommonWidgetProperties; +import org.csstudio.display.builder.model.spi.ActionInfo; +import org.csstudio.display.builder.model.widgets.ActionButtonWidget; +import org.csstudio.display.builder.runtime.WidgetRuntime; +import org.csstudio.display.builder.runtime.pv.RuntimePV; +import org.csstudio.display.builder.runtime.script.PVUtil; +import org.junit.jupiter.api.Test; +import org.phoebus.pv.PVPool; +import org.phoebus.pv.loc.LocalPVFactory; + +public class WidgetRuntimeTest { + + @Test + public void testWriteAction() + { + //Test for Write action on default pv different from ca see PR + //https://github.com/ControlSystemStudio/phoebus/pull/3412 + //Force default data source to loc:// + PVPool.default_type = LocalPVFactory.TYPE; + String pv_name = "my_pv"; + try { + RuntimePV pv = PVUtil.createPV(pv_name, 0); + //First init value + double initValue = 10; + //VDouble val = VDouble.of(initValue, Alarm.none(), org.epics.vtype.Time.now(), org.epics.vtype.Display.none()); + pv.write(initValue); + //PVUtil.writePV(pv_name, initValue, 0); + double readValue = PVUtil.getDouble(pv); + //Test in standard way + assertThat(readValue, equalTo(initValue)); + + //Test with WidgetRuntime (write Action) + ActionButtonWidget widget = new ActionButtonWidget(); + widget.setPropertyValue(CommonWidgetProperties.propPVName.getName(), pv_name); + //Add write action + //Write new value + double newValue = 20; + + List actionList = new ArrayList(); + ActionInfo writeAction = new WritePVAction("Write value", pv_name, String.valueOf(newValue)); + actionList.add(writeAction); + ActionInfos actInfos = new ActionInfos(actionList, true); + widget.setPropertyValue(CommonWidgetProperties.propActions.getName(), actInfos); + + //Create Widget Runtime + WidgetRuntime ofWidget = new WidgetRuntime(); + ofWidget.initialize(widget); + ofWidget.addPV(pv, true); + ofWidget.start(); + + ofWidget.writePV(pv_name, newValue); + + //Test the new value + readValue = PVUtil.getDouble(pv); + //Test if the new value is ok + assertThat(readValue, equalTo(newValue)); + + } catch (Exception e) { + e.printStackTrace(); + fail(e); + } + + + + + } + +} diff --git a/core/pv-ca/src/main/java/org/phoebus/pv/ca/JCA_PV.java b/core/pv-ca/src/main/java/org/phoebus/pv/ca/JCA_PV.java index a43480db21..9ed631b820 100644 --- a/core/pv-ca/src/main/java/org/phoebus/pv/ca/JCA_PV.java +++ b/core/pv-ca/src/main/java/org/phoebus/pv/ca/JCA_PV.java @@ -12,6 +12,14 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; +import org.epics.vtype.VBoolean; +import org.epics.vtype.VDouble; +import org.epics.vtype.VEnum; +import org.epics.vtype.VFloat; +import org.epics.vtype.VInt; +import org.epics.vtype.VLong; +import org.epics.vtype.VShort; +import org.epics.vtype.VString; import org.epics.vtype.VType; import org.phoebus.pv.PV; @@ -460,8 +468,36 @@ public CompletableFuture asyncWrite(final Object new_value) throws Exception return result; } - private void performWrite(final Object new_value, final PutListener put_listener) throws Exception + private void performWrite(final Object newvalue, final PutListener put_listener) throws Exception { + //Manage type of PV to convert the value in good format + VType vType = read(); + Object new_value = newvalue; + if(vType instanceof VString) { + new_value = newvalue.toString(); + } + else if(vType instanceof VDouble) { + new_value = Double.valueOf(new_value.toString()); + } + else if(vType instanceof VLong) { + new_value = Double.valueOf(new_value.toString()).longValue(); + } + else if(vType instanceof VFloat) { + new_value = Double.valueOf(new_value.toString()).floatValue(); + } + else if(vType instanceof VInt) { + new_value = Double.valueOf(new_value.toString()).intValue(); + } + else if(vType instanceof VShort) { + new_value = Double.valueOf(new_value.toString()).shortValue(); + } + else if(vType instanceof VEnum) { + new_value = Double.valueOf(new_value.toString()).intValue(); + } + else if(vType instanceof VBoolean) { + new_value = Boolean.parseBoolean(new_value.toString()); + } + if (new_value instanceof String) { if (channel.getFieldType().isBYTE() && channel.getElementCount() > 1) @@ -552,6 +588,14 @@ else if (new_value instanceof Long) channel.put(val); } } + else if (new_value instanceof Boolean) + { + final short val = ((Boolean)new_value) ? (short)1 : (short)0; + if (put_listener != null) + channel.put(val, put_listener); + else + channel.put(val); + } else if (new_value instanceof Long []) { // Channel only supports put(int[]), not long[] logger.log(Level.WARNING, "Truncating long[] to int[] for PV " + getName());