Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ public class WidgetRuntime<MW extends Widget> {
*/
// This is empty for most widgets, or contains very few PVs,
// so using List with linear lookup by name and not a HashMap
private volatile List<RuntimePV> writable_pvs = null;
// Set pv_name as Key to find the corresponding RuntimePV
private volatile Map<String,RuntimePV> writable_pvs = null;

/**
* Handlers for widget's behaviorScripts property,
Expand Down Expand Up @@ -229,14 +230,14 @@ public void start() {
// Prepare action-related PVs
final List<ActionInfo> actions = widget.propActions().getValue().getActions();
if (actions.size() > 0) {
final List<RuntimePV> action_pvs = new ArrayList<>();
final Map<String, RuntimePV> action_pvs = new HashMap<>();
for (final ActionInfo action : actions) {
if (action instanceof WritePVAction) {
final String pv_name = ((WritePVAction) action).getPV();
try {
final String expanded = MacroHandler.replace(widget.getMacrosOrProperties(), pv_name);
final RuntimePV pv = PVFactory.getPV(expanded);
action_pvs.add(pv);
action_pvs.put(expanded, pv);
addPV(pv, true);
} catch (Exception ex) {
logger.log(Level.WARNING, widget + " cannot start action to write PV '" + pv_name + "'", ex);
Expand Down Expand Up @@ -407,18 +408,20 @@ public void writePV(final String pv_name, final Object value) throws Exception {
name_to_check = name_to_check.substring(0, sep);
}
awaitStartup();
final List<RuntimePV> safe_pvs = writable_pvs;
if (safe_pvs != null)
for (final RuntimePV pv : safe_pvs)
if (pv.getName().equals(name_to_check)) {
final Map<String, RuntimePV> safe_pvs = writable_pvs;
if (safe_pvs != null) {
final RuntimePV pv = safe_pvs.get(name_to_check);
if(pv != null) {
try {
pv.write(value);
} catch (final Exception ex) {
throw new Exception("Failed to write " + value + " to PV " + name_to_check, ex);
}
return;
}
throw new Exception("Unknown PV '" + pv_name + "' (expanded: '" + name_to_check + "')");
else {
throw new Exception("Unknown PV '" + pv_name + "' (expanded: '" + name_to_check + "')");
}
}
}

/**
Expand All @@ -441,13 +444,15 @@ public void stop() {
awaitStartup();
widget.propClass().removePropertyListener(update_widget_class);

final List<RuntimePV> safe_pvs = writable_pvs;
if (safe_pvs != null) {
for (final RuntimePV pv : safe_pvs) {
removePV(pv);
PVFactory.releasePV(pv);
if(writable_pvs != null && !writable_pvs.isEmpty()) {
final Collection<RuntimePV> safe_pvs = writable_pvs.values();
if (safe_pvs != null) {
for (final RuntimePV pv : safe_pvs) {
removePV(pv);
PVFactory.releasePV(pv);
}
writable_pvs = null;
}
writable_pvs = null;
}

final PVNameToValueBinding binding = pv_name_binding.getAndSet(null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
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<ActionInfo> actionList = new ArrayList<ActionInfo>();
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<ActionButtonWidget> ofWidget = new WidgetRuntime<ActionButtonWidget>();
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));

//Generate a stacktrace to fix in LocalPVFactory
ofWidget.stop();

} catch (Exception e) {
e.printStackTrace();
fail(e);
}
}

}