This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import org.opentcs.customizations.controlcenter.ControlCenterInjectionModule;
|
||||
|
||||
/**
|
||||
* Loopback adapter-specific Gucie configuration for the Kernel Control Center.
|
||||
*/
|
||||
public class LoopbackPeripheralControlCenterModule
|
||||
extends
|
||||
ControlCenterInjectionModule {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public LoopbackPeripheralControlCenterModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(
|
||||
new FactoryModuleBuilder().build(LoopbackPeripheralAdapterPanelComponentsFactory.class)
|
||||
);
|
||||
|
||||
peripheralCommAdapterPanelFactoryBinder()
|
||||
.addBinding().to(LoopbackPeripheralCommAdapterPanelFactory.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import org.opentcs.customizations.kernel.KernelInjectionModule;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Loopback adapter-specific Gucie configuration for the Kernel.
|
||||
*/
|
||||
public class LoopbackPeripheralKernelModule
|
||||
extends
|
||||
KernelInjectionModule {
|
||||
|
||||
/**
|
||||
* This class's logger.
|
||||
*/
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LoopbackPeripheralKernelModule.class);
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public LoopbackPeripheralKernelModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
VirtualPeripheralConfiguration configuration
|
||||
= getConfigBindingProvider().get(
|
||||
VirtualPeripheralConfiguration.PREFIX,
|
||||
VirtualPeripheralConfiguration.class
|
||||
);
|
||||
|
||||
if (!configuration.enable()) {
|
||||
LOG.info("Peripheral loopback driver disabled by configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
bind(VirtualPeripheralConfiguration.class)
|
||||
.toInstance(configuration);
|
||||
|
||||
install(new FactoryModuleBuilder().build(LoopbackPeripheralAdapterComponentsFactory.class));
|
||||
|
||||
// tag::documentation_createCommAdapterModule[]
|
||||
peripheralCommAdaptersBinder().addBinding().to(LoopbackPeripheralCommAdapterFactory.class);
|
||||
// end::documentation_createCommAdapterModule[]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
org.opentcs.commadapter.peripheral.loopback.LoopbackPeripheralControlCenterModule
|
||||
@@ -0,0 +1,4 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
org.opentcs.commadapter.peripheral.loopback.LoopbackPeripheralKernelModule
|
||||
@@ -0,0 +1,14 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
/**
|
||||
* Defines constants regarding internationalization.
|
||||
*/
|
||||
public interface I18nLoopbackPeripheralCommAdapter {
|
||||
|
||||
/**
|
||||
* The path to the project's resource bundle.
|
||||
*/
|
||||
String BUNDLE_PATH = "i18n/org/opentcs/commadapter/peripheral/loopback/Bundle";
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
/**
|
||||
*/
|
||||
public interface LocationProperties {
|
||||
|
||||
/**
|
||||
* The key of the location property indicating that the location represents a peripheral device
|
||||
* and that it should be attached to the loopback peripheral communication adapter.
|
||||
*/
|
||||
String PROPKEY_LOOPBACK_PERIPHERAL = "tcs:loopbackPeripheral";
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import org.opentcs.data.model.Location;
|
||||
import org.opentcs.data.model.TCSResourceReference;
|
||||
|
||||
/**
|
||||
* A factory for various loopback specific instances.
|
||||
*/
|
||||
public interface LoopbackPeripheralAdapterComponentsFactory {
|
||||
|
||||
/**
|
||||
* Creates a new loopback communication adapter for the given location.
|
||||
*
|
||||
* @param location The location.
|
||||
* @return A loopback communication adapter instance.
|
||||
*/
|
||||
LoopbackPeripheralCommAdapter createLoopbackCommAdapter(TCSResourceReference<Location> location);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
/**
|
||||
* A factory for creating various comm adapter panel-specific instances.
|
||||
*/
|
||||
public interface LoopbackPeripheralAdapterPanelComponentsFactory {
|
||||
|
||||
/**
|
||||
* Creates a {@link LoopbackPeripheralCommAdapterPanel} representing the given process model's
|
||||
* content.
|
||||
*
|
||||
* @param processModel The process model to represent.
|
||||
* @return The comm adapter panel.
|
||||
*/
|
||||
LoopbackPeripheralCommAdapterPanel createPanel(LoopbackPeripheralProcessModel processModel);
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.opentcs.util.Assertions.checkState;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.opentcs.customizations.ApplicationEventBus;
|
||||
import org.opentcs.customizations.kernel.KernelExecutor;
|
||||
import org.opentcs.data.model.Location;
|
||||
import org.opentcs.data.model.PeripheralInformation;
|
||||
import org.opentcs.data.model.TCSResourceReference;
|
||||
import org.opentcs.data.peripherals.PeripheralJob;
|
||||
import org.opentcs.drivers.peripherals.BasicPeripheralCommAdapter;
|
||||
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
|
||||
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
|
||||
import org.opentcs.drivers.peripherals.PeripheralJobCallback;
|
||||
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
|
||||
import org.opentcs.drivers.peripherals.management.PeripheralProcessModelEvent;
|
||||
import org.opentcs.util.ExplainedBoolean;
|
||||
import org.opentcs.util.event.EventHandler;
|
||||
|
||||
/**
|
||||
* A {@link PeripheralCommAdapter} implementation that is doing nothing.
|
||||
*/
|
||||
public class LoopbackPeripheralCommAdapter
|
||||
extends
|
||||
BasicPeripheralCommAdapter {
|
||||
|
||||
/**
|
||||
* The time it takes for loopback peripherals to process a job.
|
||||
*/
|
||||
private static final Duration JOB_PROCESSING_DURATION = Duration.ofSeconds(10);
|
||||
/**
|
||||
* The kernel's executor.
|
||||
*/
|
||||
private final ScheduledExecutorService kernelExecutor;
|
||||
/**
|
||||
* The queue of tasks to be executed to simulate the processing of jobs.
|
||||
* This queue may contain at most one item at any time.
|
||||
*/
|
||||
private final Queue<Runnable> jobTaskQueue = new ArrayDeque<>();
|
||||
/**
|
||||
* A future for the current job task's execution.
|
||||
* Indicates whehter the current job task has been executed or whether it is still to be executed.
|
||||
*/
|
||||
private Future<?> currentJobFuture;
|
||||
/**
|
||||
* Whether the execution of jobs should fail.
|
||||
*/
|
||||
private boolean failJobs;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param location The reference to the location this adapter is attached to.
|
||||
* @param eventHandler The handler used to send events to.
|
||||
* @param kernelExecutor The kernel's executor.
|
||||
*/
|
||||
@Inject
|
||||
public LoopbackPeripheralCommAdapter(
|
||||
@Assisted
|
||||
TCSResourceReference<Location> location,
|
||||
@ApplicationEventBus
|
||||
EventHandler eventHandler,
|
||||
@KernelExecutor
|
||||
ScheduledExecutorService kernelExecutor
|
||||
) {
|
||||
super(new LoopbackPeripheralProcessModel(location), eventHandler);
|
||||
this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
if (isInitialized()) {
|
||||
return;
|
||||
}
|
||||
super.initialize();
|
||||
|
||||
setProcessModel(getProcessModel().withState(PeripheralInformation.State.IDLE));
|
||||
sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoopbackPeripheralProcessModel getProcessModel() {
|
||||
return (LoopbackPeripheralProcessModel) super.getProcessModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExplainedBoolean canProcess(PeripheralJob job) {
|
||||
if (!isEnabled()) {
|
||||
return new ExplainedBoolean(false, "Comm adapter not enabled.");
|
||||
}
|
||||
else if (hasJobWaitingToBeProcessed()) {
|
||||
return new ExplainedBoolean(false, "Busy processing another job.");
|
||||
}
|
||||
|
||||
return new ExplainedBoolean(true, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(PeripheralJob job, PeripheralJobCallback callback) {
|
||||
ExplainedBoolean canProcess = canProcess(job);
|
||||
checkState(
|
||||
canProcess.getValue(),
|
||||
"%s: Can't process job: %s",
|
||||
getProcessModel().getLocation().getName(),
|
||||
canProcess.getReason()
|
||||
);
|
||||
|
||||
jobTaskQueue.add(() -> {
|
||||
if (failJobs) {
|
||||
callback.peripheralJobFailed(job.getReference());
|
||||
}
|
||||
else {
|
||||
callback.peripheralJobFinished(job.getReference());
|
||||
}
|
||||
setProcessModel(getProcessModel().withState(PeripheralInformation.State.IDLE));
|
||||
sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);
|
||||
});
|
||||
|
||||
setProcessModel(getProcessModel().withState(PeripheralInformation.State.EXECUTING));
|
||||
sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);
|
||||
|
||||
if (!getProcessModel().isManualModeEnabled()) {
|
||||
currentJobFuture = kernelExecutor.schedule(
|
||||
jobTaskQueue.poll(),
|
||||
JOB_PROCESSING_DURATION.getSeconds(),
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abortJob() {
|
||||
jobTaskQueue.clear();
|
||||
if (currentJobFuture != null) {
|
||||
currentJobFuture.cancel(false);
|
||||
}
|
||||
setProcessModel(getProcessModel().withState(PeripheralInformation.State.IDLE));
|
||||
sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(PeripheralAdapterCommand command) {
|
||||
command.execute(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void connectPeripheral() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disconnectPeripheral() {
|
||||
}
|
||||
|
||||
public void enableManualMode(boolean enabled) {
|
||||
kernelExecutor.submit(() -> {
|
||||
LoopbackPeripheralProcessModel oldProcessModel = getProcessModel();
|
||||
setProcessModel(getProcessModel().withManualModeEnabled(enabled));
|
||||
|
||||
if (oldProcessModel.isManualModeEnabled() && !getProcessModel().isManualModeEnabled()) {
|
||||
// Job processing mode changed to "automatic". If there's a task that has not yet been
|
||||
// processed while the processing mode was set to "manual", make sure the task is executed
|
||||
// and schedule it for execution on the kernel executor.
|
||||
if (!jobTaskQueue.isEmpty()) {
|
||||
currentJobFuture = kernelExecutor.submit(jobTaskQueue.poll());
|
||||
}
|
||||
}
|
||||
|
||||
sendProcessModelChangedEvent(LoopbackPeripheralProcessModel.Attribute.MANUAL_MODE_ENABLED);
|
||||
});
|
||||
}
|
||||
|
||||
public void updateState(PeripheralInformation.State state) {
|
||||
kernelExecutor.submit(() -> {
|
||||
setProcessModel(getProcessModel().withState(state));
|
||||
sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);
|
||||
});
|
||||
}
|
||||
|
||||
public void triggerJobProcessing(boolean failJob) {
|
||||
if (!getProcessModel().isManualModeEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jobTaskQueue.isEmpty() || !isCurrentJobFutureDone()) {
|
||||
// There's no job to be processed or we are not yet done processing the current one.
|
||||
return;
|
||||
}
|
||||
|
||||
currentJobFuture = kernelExecutor.submit(() -> {
|
||||
failJobs = failJob;
|
||||
jobTaskQueue.poll().run();
|
||||
failJobs = false;
|
||||
});
|
||||
}
|
||||
|
||||
private boolean hasJobWaitingToBeProcessed() {
|
||||
return !jobTaskQueue.isEmpty() || !isCurrentJobFutureDone();
|
||||
}
|
||||
|
||||
private boolean isCurrentJobFutureDone() {
|
||||
if (currentJobFuture == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return currentJobFuture.isDone();
|
||||
}
|
||||
|
||||
private void sendProcessModelChangedEvent(
|
||||
LoopbackPeripheralProcessModel.Attribute attributeChanged
|
||||
) {
|
||||
getEventHandler().onEvent(
|
||||
new PeripheralProcessModelEvent(
|
||||
getProcessModel().getLocation(),
|
||||
attributeChanged.name(),
|
||||
getProcessModel()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import static org.opentcs.commadapter.peripheral.loopback.I18nLoopbackPeripheralCommAdapter.BUNDLE_PATH;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
|
||||
|
||||
/**
|
||||
* A {@link PeripheralCommAdapterDescription} for no comm adapter.
|
||||
*/
|
||||
public class LoopbackPeripheralCommAdapterDescription
|
||||
extends
|
||||
PeripheralCommAdapterDescription {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public LoopbackPeripheralCommAdapterDescription() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return ResourceBundle.getBundle(BUNDLE_PATH)
|
||||
.getString("loopbackPeripheralCommAdapterDescription.description");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import org.opentcs.data.model.Location;
|
||||
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
|
||||
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
|
||||
import org.opentcs.drivers.peripherals.PeripheralCommAdapterFactory;
|
||||
|
||||
/**
|
||||
* A factory for loopback communication adapters (virtual peripherals).
|
||||
*/
|
||||
public class LoopbackPeripheralCommAdapterFactory
|
||||
implements
|
||||
PeripheralCommAdapterFactory {
|
||||
|
||||
/**
|
||||
* The adapter components factory.
|
||||
*/
|
||||
private final LoopbackPeripheralAdapterComponentsFactory componentsFactory;
|
||||
/**
|
||||
* Indicates whether this component is initialized or not.
|
||||
*/
|
||||
private boolean initialized;
|
||||
|
||||
@Inject
|
||||
public LoopbackPeripheralCommAdapterFactory(
|
||||
LoopbackPeripheralAdapterComponentsFactory componentsFactory
|
||||
) {
|
||||
this.componentsFactory = requireNonNull(componentsFactory, "componentsFactory");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
if (isInitialized()) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void terminate() {
|
||||
if (!isInitialized()) {
|
||||
return;
|
||||
}
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PeripheralCommAdapterDescription getDescription() {
|
||||
return new LoopbackPeripheralCommAdapterDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean providesAdapterFor(Location location) {
|
||||
requireNonNull(location, "location");
|
||||
return location.getProperties().containsKey(LocationProperties.PROPKEY_LOOPBACK_PERIPHERAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PeripheralCommAdapter getAdapterFor(Location location) {
|
||||
requireNonNull(location, "location");
|
||||
return componentsFactory.createLoopbackCommAdapter(location.getReference());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="i18n/org/opentcs/commadapter/peripheral/loopback/Bundle.properties" key="loopbackPeripheralCommAdapterPanel.accessibleName" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</Property>
|
||||
</AccessibilityProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="statePanel" pref="194" max="32767" attributes="0"/>
|
||||
<Component id="jobProcessingPanel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="170" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="statePanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jobProcessingPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="165" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="statePanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Current state">
|
||||
<ResourceString PropertyName="titleX" bundle="i18n/org/opentcs/commadapter/peripheral/loopback/Bundle.properties" key="loopbackPeripheralCommAdapterPanel.panel_state.border.title" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="statePanel" noResource="true"/>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="stateLabel">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="11"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="i18n/org/opentcs/commadapter/peripheral/loopback/Bundle.properties" key="loopbackPeripheralCommAdapterPanel.label_state.text" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="stateComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="new DefaultComboBoxModel<>(Arrays.asList(PeripheralInformation.State.values()).stream().filter(state -> state != PeripheralInformation.State.NO_PERIPHERAL).toArray(PeripheralInformation.State[]::new))" type="code"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="stateComboBoxItemStateChanged"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<PeripheralInformation.State>"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="10" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jobProcessingPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Job processing">
|
||||
<ResourceString PropertyName="titleX" bundle="i18n/org/opentcs/commadapter/peripheral/loopback/Bundle.properties" key="loopbackPeripheralCommAdapterPanel.panel_jobProcessing.border.title" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JRadioButton" name="automaticModeRadioButton">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="i18n/org/opentcs/commadapter/peripheral/loopback/Bundle.properties" key="loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingAutomatic.text" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
|
||||
<EmptyBorder bottom="0" left="0" right="0" top="0"/>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[0, 0, 0, 0]"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="automaticModeRadioButton" noResource="true"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="automaticModeRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="3" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="manualModeRadioButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="i18n/org/opentcs/commadapter/peripheral/loopback/Bundle.properties" key="loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingManual.text" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
|
||||
<EmptyBorder bottom="0" left="0" right="0" top="0"/>
|
||||
</Border>
|
||||
</Property>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[0, 0, 0, 0]"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="manualModeRadioButton" noResource="true"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="manualModeRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="finishCurrentJobButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="i18n/org/opentcs/commadapter/peripheral/loopback/Bundle.properties" key="loopbackPeripheralCommAdapterPanel.button_finishCurrentJob.text" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
<Property name="name" type="java.lang.String" value="finishCurrentJobButton" noResource="true"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="finishCurrentJobButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="failCurrentJobButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="i18n/org/opentcs/commadapter/peripheral/loopback/Bundle.properties" key="loopbackPeripheralCommAdapterPanel.button_failCurrentJob.text" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
<Property name="name" type="java.lang.String" value="processCurrentJobButton" noResource="true"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="failCurrentJobButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="0" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -0,0 +1,299 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import jakarta.inject.Inject;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.util.Arrays;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.opentcs.access.KernelServicePortal;
|
||||
import org.opentcs.commadapter.peripheral.loopback.commands.EnableManualModeCommand;
|
||||
import org.opentcs.commadapter.peripheral.loopback.commands.FinishJobProcessingCommand;
|
||||
import org.opentcs.commadapter.peripheral.loopback.commands.SetStateCommand;
|
||||
import org.opentcs.customizations.ServiceCallWrapper;
|
||||
import org.opentcs.data.model.PeripheralInformation;
|
||||
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
|
||||
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
|
||||
import org.opentcs.drivers.peripherals.management.PeripheralCommAdapterPanel;
|
||||
import org.opentcs.util.CallWrapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The panel for the loopback peripheral communication adapter.
|
||||
*/
|
||||
public class LoopbackPeripheralCommAdapterPanel
|
||||
extends
|
||||
PeripheralCommAdapterPanel {
|
||||
|
||||
/**
|
||||
* This class's logger.
|
||||
*/
|
||||
private static final Logger LOG
|
||||
= LoggerFactory.getLogger(LoopbackPeripheralCommAdapterPanel.class);
|
||||
/**
|
||||
* The service portal to use.
|
||||
*/
|
||||
private final KernelServicePortal servicePortal;
|
||||
/**
|
||||
* The call wrapper to use for service calls.
|
||||
*/
|
||||
private final CallWrapper callWrapper;
|
||||
/**
|
||||
* The comm adapter's process model.
|
||||
*/
|
||||
private LoopbackPeripheralProcessModel processModel;
|
||||
|
||||
@Inject
|
||||
@SuppressWarnings("this-escape")
|
||||
public LoopbackPeripheralCommAdapterPanel(
|
||||
@Assisted
|
||||
LoopbackPeripheralProcessModel processModel,
|
||||
KernelServicePortal servicePortal,
|
||||
@ServiceCallWrapper
|
||||
CallWrapper callWrapper
|
||||
) {
|
||||
this.processModel = requireNonNull(processModel, "processModel");
|
||||
this.servicePortal = requireNonNull(servicePortal, "servicePortal");
|
||||
this.callWrapper = requireNonNull(callWrapper, "callWrapper");
|
||||
|
||||
initComponents();
|
||||
updateComponentsEnabled();
|
||||
updateComponentContents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processModelChanged(PeripheralProcessModel processModel) {
|
||||
requireNonNull(processModel, "processModel");
|
||||
if (!(processModel instanceof LoopbackPeripheralProcessModel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
this.processModel = (LoopbackPeripheralProcessModel) processModel;
|
||||
updateComponentsEnabled();
|
||||
updateComponentContents();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateComponentsEnabled() {
|
||||
boolean enabled = processModel.isCommAdapterEnabled();
|
||||
stateComboBox.setEnabled(enabled);
|
||||
finishCurrentJobButton.setEnabled(processModel.isManualModeEnabled());
|
||||
failCurrentJobButton.setEnabled(processModel.isManualModeEnabled());
|
||||
}
|
||||
|
||||
private void updateComponentContents() {
|
||||
stateComboBox.setSelectedItem(processModel.getState());
|
||||
manualModeRadioButton.setSelected(processModel.isManualModeEnabled());
|
||||
automaticModeRadioButton.setSelected(!processModel.isManualModeEnabled());
|
||||
}
|
||||
|
||||
private void sendCommAdapterCommand(PeripheralAdapterCommand command) {
|
||||
try {
|
||||
callWrapper.call(
|
||||
() -> servicePortal.getPeripheralService()
|
||||
.sendCommAdapterCommand(processModel.getLocation(), command)
|
||||
);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LOG.warn("Error sending comm adapter command '{}'", command, ex);
|
||||
}
|
||||
}
|
||||
|
||||
// FORMATTER:OFF
|
||||
// CHECKSTYLE:OFF
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always regenerated
|
||||
* by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
statePanel = new javax.swing.JPanel();
|
||||
stateLabel = new javax.swing.JLabel();
|
||||
stateComboBox = new javax.swing.JComboBox<>();
|
||||
jobProcessingPanel = new javax.swing.JPanel();
|
||||
automaticModeRadioButton = new javax.swing.JRadioButton();
|
||||
manualModeRadioButton = new javax.swing.JRadioButton();
|
||||
finishCurrentJobButton = new javax.swing.JButton();
|
||||
failCurrentJobButton = new javax.swing.JButton();
|
||||
|
||||
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/commadapter/peripheral/loopback/Bundle"); // NOI18N
|
||||
statePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("loopbackPeripheralCommAdapterPanel.panel_state.border.title"))); // NOI18N
|
||||
statePanel.setName("statePanel"); // NOI18N
|
||||
statePanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
stateLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
|
||||
stateLabel.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.label_state.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 0);
|
||||
statePanel.add(stateLabel, gridBagConstraints);
|
||||
|
||||
stateComboBox.setModel(new DefaultComboBoxModel<>(Arrays.asList(PeripheralInformation.State.values()).stream().filter(state -> state != PeripheralInformation.State.NO_PERIPHERAL).toArray(PeripheralInformation.State[]::new)));
|
||||
stateComboBox.addItemListener(new java.awt.event.ItemListener() {
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
stateComboBoxItemStateChanged(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
|
||||
statePanel.add(stateComboBox, gridBagConstraints);
|
||||
|
||||
jobProcessingPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("loopbackPeripheralCommAdapterPanel.panel_jobProcessing.border.title"))); // NOI18N
|
||||
jobProcessingPanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
automaticModeRadioButton.setSelected(true);
|
||||
automaticModeRadioButton.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingAutomatic.text")); // NOI18N
|
||||
automaticModeRadioButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
|
||||
automaticModeRadioButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
|
||||
automaticModeRadioButton.setName("automaticModeRadioButton"); // NOI18N
|
||||
automaticModeRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
automaticModeRadioButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
|
||||
jobProcessingPanel.add(automaticModeRadioButton, gridBagConstraints);
|
||||
|
||||
manualModeRadioButton.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingManual.text")); // NOI18N
|
||||
manualModeRadioButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
|
||||
manualModeRadioButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
|
||||
manualModeRadioButton.setName("manualModeRadioButton"); // NOI18N
|
||||
manualModeRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
manualModeRadioButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 3, 0, 0);
|
||||
jobProcessingPanel.add(manualModeRadioButton, gridBagConstraints);
|
||||
|
||||
finishCurrentJobButton.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.button_finishCurrentJob.text")); // NOI18N
|
||||
finishCurrentJobButton.setEnabled(false);
|
||||
finishCurrentJobButton.setName("finishCurrentJobButton"); // NOI18N
|
||||
finishCurrentJobButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
finishCurrentJobButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 3, 0, 3);
|
||||
jobProcessingPanel.add(finishCurrentJobButton, gridBagConstraints);
|
||||
|
||||
failCurrentJobButton.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.button_failCurrentJob.text")); // NOI18N
|
||||
failCurrentJobButton.setEnabled(false);
|
||||
failCurrentJobButton.setName("processCurrentJobButton"); // NOI18N
|
||||
failCurrentJobButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
failCurrentJobButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.insets = new java.awt.Insets(3, 3, 0, 3);
|
||||
jobProcessingPanel.add(failCurrentJobButton, gridBagConstraints);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(statePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 194, Short.MAX_VALUE)
|
||||
.addComponent(jobProcessingPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap(170, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(statePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jobProcessingPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(165, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
getAccessibleContext().setAccessibleName(bundle.getString("loopbackPeripheralCommAdapterPanel.accessibleName")); // NOI18N
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
// CHECKSTYLE:ON
|
||||
// FORMATTER:ON
|
||||
|
||||
private void manualModeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manualModeRadioButtonActionPerformed
|
||||
sendCommAdapterCommand(new EnableManualModeCommand(manualModeRadioButton.isSelected()));
|
||||
}//GEN-LAST:event_manualModeRadioButtonActionPerformed
|
||||
|
||||
private void automaticModeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_automaticModeRadioButtonActionPerformed
|
||||
sendCommAdapterCommand(new EnableManualModeCommand(!manualModeRadioButton.isSelected()));
|
||||
}//GEN-LAST:event_automaticModeRadioButtonActionPerformed
|
||||
|
||||
private void finishCurrentJobButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_finishCurrentJobButtonActionPerformed
|
||||
sendCommAdapterCommand(new FinishJobProcessingCommand(false));
|
||||
}//GEN-LAST:event_finishCurrentJobButtonActionPerformed
|
||||
|
||||
private void stateComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_stateComboBoxItemStateChanged
|
||||
if (evt.getStateChange() != ItemEvent.SELECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
PeripheralInformation.State selectedState
|
||||
= (PeripheralInformation.State) stateComboBox.getSelectedItem();
|
||||
if (selectedState == processModel.getState()) {
|
||||
// If the selection has changed due to an update in the process model (i.e. the user has not
|
||||
// selected an item in this panel's combo box), we don't want to send a set state command.
|
||||
return;
|
||||
}
|
||||
|
||||
sendCommAdapterCommand(
|
||||
new SetStateCommand((PeripheralInformation.State) stateComboBox.getSelectedItem())
|
||||
);
|
||||
}//GEN-LAST:event_stateComboBoxItemStateChanged
|
||||
|
||||
private void failCurrentJobButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_failCurrentJobButtonActionPerformed
|
||||
sendCommAdapterCommand(new FinishJobProcessingCommand(true));
|
||||
}//GEN-LAST:event_failCurrentJobButtonActionPerformed
|
||||
|
||||
// FORMATTER:OFF
|
||||
// CHECKSTYLE:OFF
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JRadioButton automaticModeRadioButton;
|
||||
private javax.swing.JButton failCurrentJobButton;
|
||||
private javax.swing.JButton finishCurrentJobButton;
|
||||
private javax.swing.JPanel jobProcessingPanel;
|
||||
private javax.swing.JRadioButton manualModeRadioButton;
|
||||
private javax.swing.JComboBox<PeripheralInformation.State> stateComboBox;
|
||||
private javax.swing.JLabel stateLabel;
|
||||
private javax.swing.JPanel statePanel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
// CHECKSTYLE:ON
|
||||
// FORMATTER:ON
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.opentcs.data.model.Location;
|
||||
import org.opentcs.data.model.TCSResourceReference;
|
||||
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
|
||||
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
|
||||
import org.opentcs.drivers.peripherals.management.PeripheralCommAdapterPanel;
|
||||
import org.opentcs.drivers.peripherals.management.PeripheralCommAdapterPanelFactory;
|
||||
|
||||
/**
|
||||
* A factory for creating {@link LoopbackPeripheralCommAdapterPanel} instances.
|
||||
*/
|
||||
public class LoopbackPeripheralCommAdapterPanelFactory
|
||||
implements
|
||||
PeripheralCommAdapterPanelFactory {
|
||||
|
||||
/**
|
||||
* The panel components factory to use.
|
||||
*/
|
||||
private final LoopbackPeripheralAdapterPanelComponentsFactory panelComponentsFactory;
|
||||
/**
|
||||
* Indicates whether this component is initialized or not.
|
||||
*/
|
||||
private boolean initialized;
|
||||
|
||||
@Inject
|
||||
public LoopbackPeripheralCommAdapterPanelFactory(
|
||||
LoopbackPeripheralAdapterPanelComponentsFactory panelComponentsFactory
|
||||
) {
|
||||
this.panelComponentsFactory = requireNonNull(panelComponentsFactory, "panelComponentsFactory");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
if (isInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void terminate() {
|
||||
if (!isInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PeripheralCommAdapterPanel> getPanelsFor(
|
||||
@Nonnull
|
||||
PeripheralCommAdapterDescription description,
|
||||
@Nonnull
|
||||
TCSResourceReference<Location> location,
|
||||
@Nonnull
|
||||
PeripheralProcessModel processModel
|
||||
) {
|
||||
requireNonNull(description, "description");
|
||||
requireNonNull(location, "location");
|
||||
requireNonNull(processModel, "processModel");
|
||||
|
||||
if (!providesPanelsFor(description, processModel)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
return Arrays.asList(
|
||||
panelComponentsFactory
|
||||
.createPanel((LoopbackPeripheralProcessModel) processModel)
|
||||
);
|
||||
}
|
||||
|
||||
private boolean providesPanelsFor(
|
||||
PeripheralCommAdapterDescription description,
|
||||
PeripheralProcessModel processModel
|
||||
) {
|
||||
return (description instanceof LoopbackPeripheralCommAdapterDescription)
|
||||
&& (processModel instanceof LoopbackPeripheralProcessModel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.opentcs.data.model.Location;
|
||||
import org.opentcs.data.model.PeripheralInformation;
|
||||
import org.opentcs.data.model.TCSResourceReference;
|
||||
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
|
||||
|
||||
/**
|
||||
* The process model for the loopback peripheral communication adapter.
|
||||
*/
|
||||
public class LoopbackPeripheralProcessModel
|
||||
extends
|
||||
PeripheralProcessModel
|
||||
implements
|
||||
Serializable {
|
||||
|
||||
/**
|
||||
* Whether the peripheral device is manual mode (i.e. the user triggers the job execution).
|
||||
*/
|
||||
private final boolean manualModeEnabled;
|
||||
|
||||
public LoopbackPeripheralProcessModel(TCSResourceReference<Location> location) {
|
||||
this(location, false, false, PeripheralInformation.State.UNKNOWN, false);
|
||||
}
|
||||
|
||||
private LoopbackPeripheralProcessModel(
|
||||
TCSResourceReference<Location> location,
|
||||
boolean commAdapterEnabled,
|
||||
boolean commAdapterConnected,
|
||||
PeripheralInformation.State state,
|
||||
boolean manualModeEnabled
|
||||
) {
|
||||
super(location, commAdapterEnabled, commAdapterConnected, state);
|
||||
this.manualModeEnabled = manualModeEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoopbackPeripheralProcessModel withLocation(TCSResourceReference<Location> location) {
|
||||
return new LoopbackPeripheralProcessModel(
|
||||
location,
|
||||
isCommAdapterEnabled(),
|
||||
isCommAdapterConnected(),
|
||||
getState(),
|
||||
manualModeEnabled
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoopbackPeripheralProcessModel withCommAdapterEnabled(boolean commAdapterEnabled) {
|
||||
return new LoopbackPeripheralProcessModel(
|
||||
getLocation(),
|
||||
commAdapterEnabled,
|
||||
isCommAdapterConnected(),
|
||||
getState(),
|
||||
manualModeEnabled
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoopbackPeripheralProcessModel withCommAdapterConnected(boolean commAdapterConnected) {
|
||||
return new LoopbackPeripheralProcessModel(
|
||||
getLocation(),
|
||||
isCommAdapterEnabled(),
|
||||
commAdapterConnected,
|
||||
getState(),
|
||||
manualModeEnabled
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoopbackPeripheralProcessModel withState(PeripheralInformation.State state) {
|
||||
return new LoopbackPeripheralProcessModel(
|
||||
getLocation(),
|
||||
isCommAdapterEnabled(),
|
||||
isCommAdapterConnected(),
|
||||
state,
|
||||
manualModeEnabled
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the peripheral device is manual mode (i.e. the user triggers the job
|
||||
* execution).
|
||||
*
|
||||
* @return Whether the peripheral device is manual mode.
|
||||
*/
|
||||
public boolean isManualModeEnabled() {
|
||||
return manualModeEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of the object, with the given value.
|
||||
*
|
||||
* @param manualModeEnabled The value to be set in the copy.
|
||||
* @return A copy of this object, differing in the given value.
|
||||
*/
|
||||
public LoopbackPeripheralProcessModel withManualModeEnabled(boolean manualModeEnabled) {
|
||||
return new LoopbackPeripheralProcessModel(
|
||||
getLocation(),
|
||||
isCommAdapterEnabled(),
|
||||
isCommAdapterConnected(),
|
||||
getState(),
|
||||
manualModeEnabled
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to describe what has changed in a process model.
|
||||
*/
|
||||
public enum Attribute {
|
||||
/**
|
||||
* Indicates a change of the manual mode enabled property.
|
||||
*/
|
||||
MANUAL_MODE_ENABLED,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback;
|
||||
|
||||
import org.opentcs.configuration.ConfigurationEntry;
|
||||
import org.opentcs.configuration.ConfigurationPrefix;
|
||||
|
||||
/**
|
||||
* Provides methods to configure to {@link LoopbackPeripheralCommAdapter}.
|
||||
*/
|
||||
@ConfigurationPrefix(VirtualPeripheralConfiguration.PREFIX)
|
||||
public interface VirtualPeripheralConfiguration {
|
||||
|
||||
/**
|
||||
* This configuration's prefix.
|
||||
*/
|
||||
String PREFIX = "virtualperipheral";
|
||||
|
||||
@ConfigurationEntry(
|
||||
type = "Boolean",
|
||||
description = "Whether to enable to register/enable the peripheral loopback driver.",
|
||||
changesApplied = ConfigurationEntry.ChangesApplied.ON_APPLICATION_START,
|
||||
orderKey = "0_enable"
|
||||
)
|
||||
boolean enable();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback.commands;
|
||||
|
||||
import org.opentcs.commadapter.peripheral.loopback.LoopbackPeripheralCommAdapter;
|
||||
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
|
||||
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
|
||||
|
||||
/**
|
||||
* A command to enable/disable the comm adapter's manual mode.
|
||||
*/
|
||||
public class EnableManualModeCommand
|
||||
implements
|
||||
PeripheralAdapterCommand {
|
||||
|
||||
/**
|
||||
* Whether to enable/disable manual mode.
|
||||
*/
|
||||
private final boolean enabled;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param enabled Whether to enable/disable manual mode.
|
||||
*/
|
||||
public EnableManualModeCommand(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(PeripheralCommAdapter adapter) {
|
||||
if (!(adapter instanceof LoopbackPeripheralCommAdapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoopbackPeripheralCommAdapter loopbackAdapter = (LoopbackPeripheralCommAdapter) adapter;
|
||||
loopbackAdapter.enableManualMode(enabled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback.commands;
|
||||
|
||||
import org.opentcs.commadapter.peripheral.loopback.LoopbackPeripheralCommAdapter;
|
||||
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
|
||||
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
|
||||
|
||||
/**
|
||||
* A command to trigger the comm adapter in manual mode and finish the job the simulated peripheral
|
||||
* device is currently processing.
|
||||
*/
|
||||
public class FinishJobProcessingCommand
|
||||
implements
|
||||
PeripheralAdapterCommand {
|
||||
|
||||
/**
|
||||
* Whether to fail the execution of the job the (simulated) peripheral device is currently
|
||||
* processing.
|
||||
*/
|
||||
private final boolean failJob;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param failJob Whether to fail the execution of the job the (simulated) peripheral device is
|
||||
* currently processing.
|
||||
*/
|
||||
public FinishJobProcessingCommand(boolean failJob) {
|
||||
this.failJob = failJob;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(PeripheralCommAdapter adapter) {
|
||||
if (!(adapter instanceof LoopbackPeripheralCommAdapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoopbackPeripheralCommAdapter loopbackAdapter = (LoopbackPeripheralCommAdapter) adapter;
|
||||
loopbackAdapter.triggerJobProcessing(failJob);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// SPDX-FileCopyrightText: The openTCS Authors
|
||||
// SPDX-License-Identifier: MIT
|
||||
package org.opentcs.commadapter.peripheral.loopback.commands;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.opentcs.commadapter.peripheral.loopback.LoopbackPeripheralCommAdapter;
|
||||
import org.opentcs.data.model.PeripheralInformation;
|
||||
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
|
||||
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
|
||||
|
||||
/**
|
||||
* A command to set the peripheral device's state.
|
||||
*/
|
||||
public class SetStateCommand
|
||||
implements
|
||||
PeripheralAdapterCommand {
|
||||
|
||||
/**
|
||||
* The peripheral device state to set.
|
||||
*/
|
||||
private final PeripheralInformation.State state;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param state The peripheral device state to set.
|
||||
*/
|
||||
public SetStateCommand(
|
||||
@Nonnull
|
||||
PeripheralInformation.State state
|
||||
) {
|
||||
this.state = requireNonNull(state, "state");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(PeripheralCommAdapter adapter) {
|
||||
if (!(adapter instanceof LoopbackPeripheralCommAdapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoopbackPeripheralCommAdapter loopbackAdapter = (LoopbackPeripheralCommAdapter) adapter;
|
||||
loopbackAdapter.updateState(state);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: CC-BY-4.0
|
||||
|
||||
loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingManual.text=Manual mode
|
||||
loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingAutomatic.text=Automatic mode
|
||||
loopbackPeripheralCommAdapterPanel.panel_state.border.title=Current state
|
||||
loopbackPeripheralCommAdapterPanel.panel_jobProcessing.border.title=Job processing
|
||||
loopbackPeripheralCommAdapterPanel.label_state.text=State:
|
||||
loopbackPeripheralCommAdapterPanel.label_pausePeripheral.text=Pause peripheral:
|
||||
loopbackPeripheralCommAdapterPanel.button_failCurrentJob.text=Fail current job
|
||||
loopbackPeripheralCommAdapterPanel.button_finishCurrentJob.text=Finish current job
|
||||
loopbackPeripheralCommAdapterPanel.accessibleName=Loopback options
|
||||
loopbackPeripheralCommAdapterDescription.description=Loopback adapter (virtual peripheral)
|
||||
@@ -0,0 +1,13 @@
|
||||
# SPDX-FileCopyrightText: The openTCS Authors
|
||||
# SPDX-License-Identifier: CC-BY-4.0
|
||||
|
||||
loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingManual.text=Manuell
|
||||
loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingAutomatic.text=Automatik
|
||||
loopbackPeripheralCommAdapterPanel.panel_state.border.title=Aktueller Zustand
|
||||
loopbackPeripheralCommAdapterPanel.panel_jobProcessing.border.title=Auftragsbearbeitung
|
||||
loopbackPeripheralCommAdapterPanel.label_state.text=Zustand:
|
||||
loopbackPeripheralCommAdapterPanel.label_pausePeripheral.text=Peripherie anhalten:
|
||||
loopbackPeripheralCommAdapterPanel.button_failCurrentJob.text=Aktuellen Auftrag fehlschlagen lassen
|
||||
loopbackPeripheralCommAdapterPanel.button_finishCurrentJob.text=Aktuellen Auftrag abschlie\u00dfen
|
||||
loopbackPeripheralCommAdapterPanel.accessibleName=Loopback-Optionen
|
||||
loopbackPeripheralCommAdapterDescription.description=Loopback-Treiber (virtuelle Peripherie)
|
||||
Reference in New Issue
Block a user