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 @@ -43,6 +43,7 @@
import org.csstudio.scan.util.IOUtils;
import org.csstudio.scan.util.PathUtil;
import org.phoebus.framework.persistence.XMLUtil;
import org.phoebus.util.time.TimestampFormats;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

Expand Down Expand Up @@ -402,12 +403,26 @@ public Collection<DeviceInfo> getScanDevices(final long id) throws Exception
* @param name Name of the new scan
* @param xml_commands XML commands of the scan to submit
* @param queue Submit to queue or for immediate execution?
* @param scheduled Time at which to run the scan
* @return Scan ID
* @throws Exception on error
*/
public long submitScan(final String name, final String xml_commands, final boolean queue) throws Exception
public long submitScan(
final String name,
final String xml_commands,
final boolean queue,
Instant scheduled
) throws Exception
{
final HttpURLConnection connection = connect("/scan/" + name, queue ? "" : "queue=false", long_timeout);
List<String> query = new ArrayList<>();
if (!queue) {
query.add("queue=false");
}
if (scheduled != null) {
query.add("scheduled=" + TimestampFormats.SECONDS_FORMAT.format(scheduled));
}

final HttpURLConnection connection = connect("/scan/" + name, String.join("&", query), long_timeout);
connection.setReadTimeout(0);
try
{
Expand All @@ -427,6 +442,10 @@ public long submitScan(final String name, final String xml_commands, final boole
}
}

public long submitScan(final String name, final String xml_commands, final boolean queue) throws Exception {
return submitScan(name, xml_commands, queue, null);
}

/** Submit a scan for simulation
* @param xml_commands XML commands of the scan to submit
* @return Scan ID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public class ScanInfoModel
* @throws Exception on error creating the initial instance
* @see #release()
*/
public static ScanInfoModel getInstance() throws Exception
public static ScanInfoModel getInstance()
{
synchronized (ScanInfoModel.class)
{
Expand Down Expand Up @@ -124,7 +124,7 @@ public void removeListener(final ScanInfoModelListener listener)
}

/** Start model, i.e. connect to server, poll, ... */
private void start() throws Exception
private void start()
{
final long poll_period = Preferences.poll_period;
poller = new Thread(new Runnable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ public enum ScanState
Finished("Finished - OK", false, true),

/** Scan that executed in the past; data has been logged */
Logged("Logged", false, true);
Logged("Logged", false, true),

/** Scan is waiting to be executed */
Scheduled("Scheduled", false, false);

final private String name;
final private boolean active;
Expand Down
2 changes: 2 additions & 0 deletions app/scan/ui/src/main/java/org/csstudio/scan/ui/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public class Messages
public static String scan_remove;
public static String scan_resume;
public static String scan_resume_all;
public static String scan_schedule;
public static String scan_schedule_unqueued;
public static String scan_simulate;
public static String scan_submit;
public static String scan_submit_unqueued;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
Expand Down Expand Up @@ -249,7 +250,33 @@ private ToolBar createToolbar()
jump_to_current.setOnAction(event -> scan_tree.revealActiveItem(jump_to_current.isSelected()));

final Button[] undo_redo = UndoButtons.createButtons(undo);
return new ToolBar(info_text, ToolbarHelper.createStrut(), buttons, ToolbarHelper.createSpring(), undo_redo[0], undo_redo[1]);

final Button schedule_button = new Button();
schedule_button.setGraphic(ImageCache.getImageView(ScanSystem.class, "/icons/clock.png"));
schedule_button.setTooltip(new Tooltip(Messages.scan_schedule));
schedule_button.setOnAction(event -> schedule(true));

final Button run_button = new Button();
run_button.setGraphic(ImageCache.getImageView(ScanSystem.class, "/icons/run.png"));
run_button.setTooltip(new Tooltip(Messages.scan_submit));
run_button.setOnAction(event -> submitOrSimulate(true));

final Button simulate_button = new Button();
simulate_button.setGraphic(ImageCache.getImageView(ScanSystem.class, "/icons/simulate.png"));
simulate_button.setTooltip(new Tooltip(Messages.scan_simulate));
simulate_button.setOnAction(event -> submitOrSimulate(null));

return new ToolBar(
info_text,
ToolbarHelper.createStrut(),
buttons,
ToolbarHelper.createSpring(),
undo_redo[0],
undo_redo[1],
schedule_button,
simulate_button,
run_button
);
}

private void createContextMenu()
Expand All @@ -266,6 +293,14 @@ private void createContextMenu()
ImageCache.getImageView(ImageCache.class, "/icons/delete.png"));
delete.setOnAction(event -> scan_tree.cutToClipboard());

final MenuItem schedule = new MenuItem(Messages.scan_schedule,
ImageCache.getImageView(ScanSystem.class, "/icons/clock.png"));
schedule.setOnAction(event -> schedule(true));

final MenuItem schedule_unqueued = new MenuItem(Messages.scan_schedule_unqueued,
ImageCache.getImageView(ScanSystem.class, "/icons/clock.png"));
schedule_unqueued.setOnAction(event -> schedule(false));

final MenuItem simulate = new MenuItem(Messages.scan_simulate,
ImageCache.getImageView(ScanSystem.class, "/icons/simulate.png"));
simulate.setOnAction(event -> submitOrSimulate(null));
Expand All @@ -284,12 +319,26 @@ private void createContextMenu()

final ContextMenu menu = new ContextMenu(copy, paste, delete,
new SeparatorMenuItem(),
simulate, submit, submit_unqueued,
schedule, schedule_unqueued, simulate, submit, submit_unqueued,
new SeparatorMenuItem(),
open_monitor);
setContextMenu(menu);
}

private void schedule(final Boolean queued) {
final String xml_commands;
try {
xml_commands = XMLCommandWriter.toXMLString(model.getCommands());
} catch (Exception e) {
throw new RuntimeException(e);
}
final ScanClient scan_client = new ScanClient(Preferences.host, Preferences.port);
ScheduledScanDialog dialog = new ScheduledScanDialog(scan_name, scan_client, xml_commands, queued);
DialogHelper.positionDialog(dialog, this, 100, 100);
Optional<Long> scan_id = dialog.showAndWait();
scan_id.ifPresent(this::attachScan);
}

/** @param how true/false to submit queue/un-queued, <code>null</code> to simulate */
private void submitOrSimulate(final Boolean how)
{
Expand Down Expand Up @@ -362,7 +411,7 @@ UndoableActionManager getUndo()
* @param id Scan ID
* @throws Exception on error
*/
void attachScan(final long id) throws Exception
void attachScan(final long id)
{
active_scan = id;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.csstudio.scan.ui.editor;

import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import org.csstudio.scan.client.ScanClient;
import org.phoebus.ui.time.DateTimePane;

import java.time.Instant;
import java.time.ZoneId;


public class ScheduledScanDialog extends Dialog<Long> {
final String scan_name;
final ScanClient scan_client;
final String script_xml;
final boolean queued;

public ScheduledScanDialog(String scan_name, ScanClient scan_client, String script_xml) {
this(scan_name, scan_client, script_xml, true);
}

public ScheduledScanDialog(String scan_name, ScanClient scan_client, String script_xml, boolean queued) {
this.scan_name = scan_name;
this.scan_client = scan_client;
this.script_xml = script_xml;
this.queued = queued;

setTitle("Schedule " + scan_name);
getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);

final DateTimePane datetime = new DateTimePane();
getDialogPane().setContent(datetime);

setResultConverter(button ->
{
if (button == ButtonType.OK) {
try {
return scan_client.submitScan(
scan_name,
script_xml,
queued,
datetime.getInstant()
);
}
catch (Exception e) {
return null;
}
} else {
return null;
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -260,17 +260,19 @@ private static int rankState(final ScanState state)
{
switch (state)
{
case Running: // Most important, happening right now
case Running: // Most important, happening right now
return 7;
case Paused: // Very similar to a running state
return 6;
case Paused: // Very similar to a running state
case Idle: // About to run next
return 5;
case Idle: // About to run next
case Scheduled: // Scheduled to run in the future
return 4;
case Failed: // Of the not running ones, failure is important to know
case Failed: // Of the not running ones, failure is important to know
return 3;
case Aborted: // Aborted on purpose
case Aborted: // Aborted on purpose
return 2;
case Finished:// Water down the bridge
case Finished: // Water down the bridge
return 1;
case Logged:
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ protected void updateItem(final ScanState state, final boolean empty)
show(getResume());
show(getAbort());
break;
case Scheduled:
show(getAbort());
break;
case Aborted:
case Failed:
case Finished:
Expand All @@ -201,6 +204,7 @@ static Color getStateColor(final ScanState state)
case Finished: return Color.DARKGREEN;
case Paused: return Color.GRAY;
case Running: return Color.GREEN;
case Scheduled: return Color.DARKBLUE;
default: return Color.BLACK;
}
}
Expand Down
Binary file added app/scan/ui/src/main/resources/icons/clock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ scan_pause_all=Pause all running scans
scan_remove=Remove this scan
scan_resume=Resume execution
scan_resume_all=Resume all paused scans
scan_schedule=Schedule scan
scan_schedule_unqueued=Schedule scan (not queued)
scan_simulate=Simulate scan
scan_submit=Submit scan
scan_submit_unqueued=Submit scan (not queued)
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void decrement(final int steps)
public void increment(final int steps)
{
final int value = getValue() + 1;
if (value != max)
if (value != max + 1)
setValue(value);
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
******************************************************************************/
package org.csstudio.scan.server;

import java.time.LocalDateTime;
import java.time.Instant;
import java.util.List;

import org.csstudio.scan.data.ScanData;
Expand Down Expand Up @@ -59,10 +59,11 @@ public interface ScanServer
* @param pre_post Perform the pre- and post-scans?
* @param timeout_secs Timeout in seconds or 0
* @param deadline Deadline by which scan will be aborted or <code>null</code>
* @param scheduled Datetime at which the scan should be executed (should be before the deadline, if provided)
* @return ID that uniquely identifies the scan
* @throws Exception on error
*/
public long submitScan(String scan_name, String commands_as_xml, boolean queue, boolean pre_post, long timeout_secs, LocalDateTime deadline) throws Exception;
public long submitScan(String scan_name, String commands_as_xml, boolean queue, boolean pre_post, long timeout_secs, Instant deadline, Instant scheduled) throws Exception;

/** Query server for scans
* @return Info for each scan on the server, most recently submitted scan first
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.List;
import java.util.logging.Level;

Expand Down Expand Up @@ -88,7 +88,8 @@ protected void doPost(final HttpServletRequest request,
{
// Timeout or deadline?
long timeout_secs = 0;
LocalDateTime deadline = null;
Instant deadline = null;
Instant scheduled = null;
String text = request.getParameter("timeout");
if (text != null)
try
Expand All @@ -107,7 +108,7 @@ protected void doPost(final HttpServletRequest request,
{
try
{
deadline = LocalDateTime.from(TimestampFormats.SECONDS_FORMAT.parse(text));
deadline = Instant.from(TimestampFormats.SECONDS_FORMAT.parse(text));
}
catch (Exception ex)
{
Expand All @@ -118,14 +119,37 @@ protected void doPost(final HttpServletRequest request,
throw new Exception("Cannot specify both timeout and deadline");
}

// Execute pre/post commands unless "?pre_post=false"

text = request.getParameter("scheduled");
if (text != null && !"0000-00-00 00:00:00".equals(text))
{
try
{
scheduled = Instant.from(TimestampFormats.SECONDS_FORMAT.parse(text));
}
catch (Exception ex)
{
throw new Exception("Invalid scheduled time '" + text + "'");
}
}

// Read scan commands
final String scan_commands = IOUtils.toString(request.getInputStream());

// Submit scan
if (logger.isLoggable(Level.FINE))
logger.log(Level.FINE, "Scan '" + scan_name + "':\n" + scan_commands);

final long scan_id = scan_server.submitScan(scan_name, scan_commands, queue, pre_post, timeout_secs, deadline);
final long scan_id = scan_server.submitScan(
scan_name,
scan_commands,
queue,
pre_post,
timeout_secs,
deadline,
scheduled
);

// Return scan ID
out.print("<id>");
Expand Down
Loading