Skip to content
Merged
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
6 changes: 3 additions & 3 deletions services/scan-server/.classpath
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry combineaccessrules="false" kind="src" path="/phoebus-target"/>
<classpathentry combineaccessrules="false" kind="src" path="/core-framework"/>
<classpathentry combineaccessrules="false" kind="src" path="/core-util"/>
<classpathentry combineaccessrules="false" kind="src" path="/core-pv"/>
<classpathentry combineaccessrules="false" kind="src" path="/core-pv-ca"/>
<classpathentry combineaccessrules="false" kind="src" path="/core-pv-pva"/>
<classpathentry combineaccessrules="false" kind="src" path="/core-vtype"/>
<classpathentry combineaccessrules="false" kind="src" path="/core-vtype"/>
<classpathentry combineaccessrules="false" kind="src" path="/app-scan-model"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
<classpathentry combineaccessrules="false" kind="src" path="/phoebus-target"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011-2018 Oak Ridge National Laboratory.
* Copyright (c) 2011-2026 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -111,15 +111,20 @@ public String[] getDeviceNames(final MacroContext macros) throws Exception
return device_names.toArray(new String[device_names.size()]);
}

private double getLoopStart()
/** @return Lower loop limit */
double getLoopStart()
{
return Math.min(command.getStart(), command.getEnd());
}
private double getLoopEnd()

/** @return Upper loop limit */
double getLoopEnd()
{
return Math.max(command.getStart(), command.getEnd());
}
private double getLoopStep()

/** @return Loop step, might toggle direction */
double getLoopStep()
{
final double step = direction * command.getStepSize();
// Revert direction for next iteration of the complete loop?
Expand All @@ -128,10 +133,27 @@ private double getLoopStep()
return step;
}

public int getNumSteps() {
/** @return Number of loop steps */
int getNumSteps()
{
return (int)Math.ceil(Math.abs(((command.getEnd() - command.getStart()) / command.getStepSize()))) + 1;
}

/** @param start Start value, might be upper or lower limit
* @param step Loop step value, positive or negative
* @param i Loop index
* @return Loop value
*/
double computeStep(double start, double step, int i)
{
// Compute loop value, but limit to upper or lower
// end depending on step direction
if (step >= 0)
return Math.min(start + i * step, getLoopEnd());
else
return Math.max(start + i * step, getLoopStart());
}

/** {@inheritDoc} */
@Override
public void simulate(final SimulationContext context) throws Exception
Expand All @@ -143,7 +165,7 @@ public void simulate(final SimulationContext context) throws Exception
double start = step < 0 ? getLoopEnd() : getLoopStart();
int num_steps = getNumSteps();
for (int i = 0; i < num_steps; i++)
simulateStep(context, device, start + i * step);
simulateStep(context, device, computeStep(start, step, i));
}

/** Simulate one step in the loop iteration
Expand Down Expand Up @@ -211,7 +233,7 @@ public void execute(final ScanContext context) throws Exception
int num_steps = getNumSteps();

for (int i = 0; i < num_steps; i++)
executeStep(context, device, condition, readback, start + i * step);
executeStep(context, device, condition, readback, computeStep(start, step, i));
}

/** Execute one step of the loop
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*******************************************************************************
* Copyright (c) 2026 Oak Ridge National Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The scan engine idea is based on the "ScanEngine" developed
* by the Software Services Group (SSG), Advanced Photon Source,
* Argonne National Laboratory,
* Copyright (c) 2011 , UChicago Argonne, LLC.
*
* This implementation, however, contains no SSG "ScanEngine" source code
* and is not endorsed by the SSG authors.
******************************************************************************/
package org.csstudio.scan.server.command;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.List;

import org.csstudio.scan.command.LoopCommand;
import org.junit.jupiter.api.Test;

/** JUnit test for loop */
public class LoopTest
{
@Test
void testNormalLoop() throws Exception
{
LoopCommand cmd = new LoopCommand("loc://x(0)", 1.0, 10.0, 0.5, List.of());
LoopCommandImpl impl = new LoopCommandImpl(cmd);

System.out.println(cmd);

double step = impl.getLoopStep();
double start = step < 0 ? impl.getLoopEnd() : impl.getLoopStart();
int num_steps = impl.getNumSteps();

Check warning on line 38 in services/scan-server/src/test/java/org/csstudio/scan/server/command/LoopTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ3Zc5T9klImiuM3ywOp&open=AZ3Zc5T9klImiuM3ywOp&pullRequest=3795

double last = Double.NaN;
for (int i = 0; i < num_steps; i++)
{
last = impl.computeStep(start, step, i);
System.out.println(last);
}
assertEquals(10.0, last);
}

@Test
void testUpwardsLoop() throws Exception
{
LoopCommand cmd = new LoopCommand("loc://x(0)", 1.0, 1.1, 5.0, List.of());
LoopCommandImpl impl = new LoopCommandImpl(cmd);

System.out.println(cmd);

double step = impl.getLoopStep();
double start = step < 0 ? impl.getLoopEnd() : impl.getLoopStart();
int num_steps = impl.getNumSteps();

Check warning on line 59 in services/scan-server/src/test/java/org/csstudio/scan/server/command/LoopTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ3Zc5T-klImiuM3ywOq&open=AZ3Zc5T-klImiuM3ywOq&pullRequest=3795

double last = Double.NaN;
for (int i = 0; i < num_steps; i++)
{
last = impl.computeStep(start, step, i);
System.out.println(last);
}
assertEquals(1.1, last);
}

@Test
void testDownwardsLoop() throws Exception
{
LoopCommand cmd = new LoopCommand("loc://x(0)", 1.1, 1.0, -5.0, List.of());
LoopCommandImpl impl = new LoopCommandImpl(cmd);

System.out.println(cmd);

double step = impl.getLoopStep();
double start = step < 0 ? impl.getLoopEnd() : impl.getLoopStart();
int num_steps = impl.getNumSteps();

Check warning on line 80 in services/scan-server/src/test/java/org/csstudio/scan/server/command/LoopTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ3Zc5T-klImiuM3ywOr&open=AZ3Zc5T-klImiuM3ywOr&pullRequest=3795

double last = Double.NaN;
for (int i = 0; i < num_steps; i++)
{
last = impl.computeStep(start, step, i);
System.out.println(last);
}
assertEquals(1.0, last);
}

@Test
void testTogglingLoop() throws Exception
{
LoopCommand cmd = new LoopCommand("loc://x(0)", 1.0, 1.1, -5.0, List.of());
LoopCommandImpl impl = new LoopCommandImpl(cmd);

System.out.println(cmd);

double step = impl.getLoopStep();
double start = step < 0 ? impl.getLoopEnd() : impl.getLoopStart();
int num_steps = impl.getNumSteps();

Check warning on line 101 in services/scan-server/src/test/java/org/csstudio/scan/server/command/LoopTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=ControlSystemStudio_phoebus&issues=AZ3Zc5T-klImiuM3ywOs&open=AZ3Zc5T-klImiuM3ywOs&pullRequest=3795

double last = Double.NaN;
for (int i = 0; i < num_steps; i++)
{
last = impl.computeStep(start, step, i);
System.out.println(last);
}
assertEquals(1.0, last);

// Run loop again, expect toggled direction
step = impl.getLoopStep();
start = step < 0 ? impl.getLoopEnd() : impl.getLoopStart();
num_steps = impl.getNumSteps();
for (int i = 0; i < num_steps; i++)
{
last = impl.computeStep(start, step, i);
System.out.println(last);
}
assertEquals(1.1, last);
}
}
Loading