[pidcontroller] Use framework scheduler and remove custom Action module (#10806)

* [pidcontroller] Use framework scheduler and remove custom Action module

Signed-off-by: Fabian Wolter <github@fabian-wolter.de>
This commit is contained in:
Fabian Wolter 2021-06-08 08:07:24 +02:00 committed by GitHub
parent 6141d69da3
commit cf13bb8275
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 250 deletions

View File

@ -14,7 +14,12 @@ A PID controller can be used for closed-loop controls. For example:
## Modules
The PID controller can be used in openHAB's [rule engine](https://www.openhab.org/docs/configuration/rules-dsl.html). This automation provides a trigger and an action module.
The PID controller can be used in openHAB's [rule engine](https://www.openhab.org/docs/configuration/rules-dsl.html).
This automation provides a trigger module ("PID controller triggers").
The return value is used to feed the Action module "Item Action" aka "send a command", which controls the actuator.
To configure a rule, you need to add a Trigger ("PID controller triggers") and an Action ("Item Action").
Select the Item you like to control in the "Item Action" and leave the command empty.
### Trigger
@ -32,27 +37,18 @@ This is then transferred to the action module.
| `kdTimeConstant` | Decimal | D-T1: [Derivative Gain Time Constant](#derivative-time-constant-d-t1-parameter) in sec. | Y |
| `commandItem` | String | Send a String "RESET" to this item to reset the I and the D part to 0. | N |
| `loopTime` | Decimal | The interval the output value will be updated in milliseconds. Note: the output will also be updated when the input value or the setpoint changes. | Y |
| `pInspector` | Item | Name of the debug Item for the current P part | N |
| `iInspector` | Item | Name of the debug Item for the current I part | N |
| `dInspector` | Item | Name of the debug Item for the current D part | N |
| `eInspector` | Item | Name of the debug Item for the current regulation difference (error) | N |
The `loopTime` should be max a tenth of the system response.
E.g. the heating needs 10 min to heat up the room, the loop time should be max 1 min.
Lower values won't harm, but need more calculation resources.
### Action
This module writes the PID controller's output value into the `output` Item and provides debugging abilities.
| Name | Type | Description | Required |
|--------------|------|----------------------------------------------------------------------|----------|
| `output` | Item | Name of the output Item (e.g. the valve actuator 0-100%) | Y |
| `pInspector` | Item | Name of the debug Item for the current P part | N |
| `iInspector` | Item | Name of the debug Item for the current I part | N |
| `dInspector` | Item | Name of the debug Item for the current D part | N |
| `eInspector` | Item | Name of the debug Item for the current regulation difference (error) | N |
You can view the internal P, I and D parts of the controller with the inspector Items.
These values are useful when tuning the controller.
They are updated everytime the output is updated.
They are updated every time the output is updated.
## Proportional (P) Gain Parameter
@ -112,8 +108,8 @@ This results in quite reasonable working systems in most cases.
So, this will be described in the following.
To be able to proceed with this method, you need to visualize the input and the output value of the PID controller over time.
It's also good to visualize the individual P, I and D parts (these are forming the output value) via the inspector Items.
The visualization can be done by the analyze function in Main UI or by adding a persistence and use Grafana for example.
It's also good to visualize the individual P, I and D parts (these are forming the output value) via the inspector items.
The visualization could be done by adding a persistence and use Grafana for example.
After you added a [Rule](https://www.openhab.org/docs/configuration/rules-dsl.html) with above trigger and action module and configured those, proceed with the following steps:

View File

@ -36,5 +36,5 @@ public class PIDControllerConstants {
public static final String I_INSPECTOR = "iInspector";
public static final String D_INSPECTOR = "dInspector";
public static final String E_INSPECTOR = "eInspector";
public static final String OUTPUT = "output";
public static final String COMMAND = "command";
}

View File

@ -17,9 +17,7 @@ import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerActionHandler;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerTriggerHandler;
import org.openhab.core.automation.Action;
import org.openhab.core.automation.Module;
import org.openhab.core.automation.Trigger;
import org.openhab.core.automation.handler.BaseModuleHandlerFactory;
@ -39,8 +37,7 @@ import org.osgi.service.component.annotations.Reference;
@Component(service = ModuleHandlerFactory.class, configurationPid = "action.pidcontroller")
@NonNullByDefault
public class PIDControllerModuleHandlerFactory extends BaseModuleHandlerFactory {
private static final Collection<String> TYPES = Set.of(PIDControllerTriggerHandler.MODULE_TYPE_ID,
PIDControllerActionHandler.MODULE_TYPE_ID);
private static final Collection<String> TYPES = Set.of(PIDControllerTriggerHandler.MODULE_TYPE_ID);
private ItemRegistry itemRegistry;
private EventPublisher eventPublisher;
private BundleContext bundleContext;
@ -63,8 +60,6 @@ public class PIDControllerModuleHandlerFactory extends BaseModuleHandlerFactory
switch (module.getTypeUID()) {
case PIDControllerTriggerHandler.MODULE_TYPE_ID:
return new PIDControllerTriggerHandler((Trigger) module, itemRegistry, eventPublisher, bundleContext);
case PIDControllerActionHandler.MODULE_TYPE_ID:
return new PIDControllerActionHandler((Action) module, itemRegistry, eventPublisher);
}
return null;

View File

@ -1,84 +0,0 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.automation.pidcontroller.internal.handler;
import static org.openhab.automation.pidcontroller.internal.PIDControllerConstants.AUTOMATION_NAME;
import java.math.BigDecimal;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.Action;
import org.openhab.core.automation.handler.ActionHandler;
import org.openhab.core.automation.handler.BaseModuleHandler;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.items.events.ItemCommandEvent;
import org.openhab.core.items.events.ItemEventFactory;
import org.openhab.core.library.types.DecimalType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
* @author Fabian Wolter - Add PID debugging items
*/
@NonNullByDefault
public class PIDControllerActionHandler extends BaseModuleHandler<Action> implements ActionHandler {
public static final String MODULE_TYPE_ID = AUTOMATION_NAME + ".action";
private final Logger logger = LoggerFactory.getLogger(PIDControllerActionHandler.class);
private ItemRegistry itemRegistry;
private EventPublisher eventPublisher;
public PIDControllerActionHandler(Action module, ItemRegistry itemRegistry, EventPublisher eventPublisher) {
super(module);
this.itemRegistry = itemRegistry;
this.eventPublisher = eventPublisher;
}
@Override
public @Nullable Map<String, Object> execute(Map<String, Object> context) {
final Configuration configuration = module.getConfiguration();
context.forEach((k, v) -> {
// Remove triggername from key to get raw trigger param
String itemKey = k.substring(k.lastIndexOf('.') + 1);
String itemName = (String) configuration.get(itemKey);
if (itemName == null || itemName.isBlank()) {
// try original key name (<triggername>.<trigger_param>)
itemName = (String) configuration.get(k);
if (itemName == null || itemName.isBlank()) {
return;
}
}
if (v instanceof BigDecimal) {
final BigDecimal command = (BigDecimal) v;
final DecimalType outputValue = new DecimalType(command);
final ItemCommandEvent itemCommandEvent = ItemEventFactory.createCommandEvent(itemName, outputValue);
eventPublisher.post(itemCommandEvent);
} else {
logger.warn(
"Command was not posted because either the configuration was not correct or a service was missing: ItemName: {}, Command: {}, eventPublisher: {}, ItemRegistry: {}",
itemName, v, eventPublisher, itemRegistry);
}
});
return null;
}
}

View File

@ -15,14 +15,10 @@ package org.openhab.automation.pidcontroller.internal.handler;
import static org.openhab.automation.pidcontroller.internal.PIDControllerConstants.*;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
@ -32,7 +28,6 @@ import org.openhab.core.automation.ModuleHandlerCallback;
import org.openhab.core.automation.Trigger;
import org.openhab.core.automation.handler.BaseTriggerModuleHandler;
import org.openhab.core.automation.handler.TriggerHandlerCallback;
import org.openhab.core.common.NamedThreadFactory;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.events.Event;
import org.openhab.core.events.EventFilter;
@ -44,6 +39,7 @@ import org.openhab.core.items.ItemRegistry;
import org.openhab.core.items.events.ItemEventFactory;
import org.openhab.core.items.events.ItemStateChangedEvent;
import org.openhab.core.items.events.ItemStateEvent;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
@ -63,18 +59,19 @@ public class PIDControllerTriggerHandler extends BaseTriggerModuleHandler implem
public static final String MODULE_TYPE_ID = AUTOMATION_NAME + ".trigger";
private static final Set<String> SUBSCRIBED_EVENT_TYPES = Set.of(ItemStateEvent.TYPE, ItemStateChangedEvent.TYPE);
private final Logger logger = LoggerFactory.getLogger(PIDControllerTriggerHandler.class);
private final ScheduledExecutorService scheduler = Executors
.newSingleThreadScheduledExecutor(new NamedThreadFactory("automation-" + AUTOMATION_NAME, true));
private final ServiceRegistration<?> eventSubscriberRegistration;
private final PIDController controller;
private final int loopTimeMs;
private @Nullable ScheduledFuture<?> controllerjob;
private long previousTimeMs = System.currentTimeMillis();
private Item inputItem;
private Item setpointItem;
private Optional<String> commandTopic;
private EventFilter eventFilter;
private EventPublisher eventPublisher;
private @Nullable String pInspector;
private @Nullable String iInspector;
private @Nullable String dInspector;
private @Nullable String eInspector;
public PIDControllerTriggerHandler(Trigger module, ItemRegistry itemRegistry, EventPublisher eventPublisher,
BundleContext bundleContext) {
@ -109,6 +106,10 @@ public class PIDControllerTriggerHandler extends BaseTriggerModuleHandler implem
double kiAdjuster = getDoubleFromConfig(config, CONFIG_KI_GAIN);
double kdAdjuster = getDoubleFromConfig(config, CONFIG_KD_GAIN);
double kdTimeConstant = getDoubleFromConfig(config, CONFIG_KD_TIMECONSTANT);
pInspector = (String) config.get(P_INSPECTOR);
iInspector = (String) config.get(I_INSPECTOR);
dInspector = (String) config.get(D_INSPECTOR);
eInspector = (String) config.get(E_INSPECTOR);
loopTimeMs = ((BigDecimal) requireNonNull(config.get(CONFIG_LOOP_TIME), CONFIG_LOOP_TIME + " is not set"))
.intValue();
@ -118,17 +119,21 @@ public class PIDControllerTriggerHandler extends BaseTriggerModuleHandler implem
eventFilter = event -> {
String topic = event.getTopic();
return topic.equals("openhab/items/" + inputItemName + "/state")
|| topic.equals("openhab/items/" + inputItemName + "/statechanged")
|| topic.equals("openhab/items/" + setpointItemName + "/statechanged")
return ("openhab/items/" + inputItemName + "/state").equals(topic)
|| ("openhab/items/" + inputItemName + "/statechanged").equals(topic)
|| ("openhab/items/" + setpointItemName + "/statechanged").equals(topic)
|| commandTopic.map(t -> topic.equals(t)).orElse(false);
};
eventSubscriberRegistration = bundleContext.registerService(EventSubscriber.class.getName(), this, null);
eventPublisher.post(ItemEventFactory.createCommandEvent(inputItemName, RefreshType.REFRESH));
}
controllerjob = scheduler.scheduleWithFixedDelay(this::calculate, 0, loopTimeMs, TimeUnit.MILLISECONDS);
@Override
public void setCallback(ModuleHandlerCallback callback) {
super.setCallback(callback);
getCallback().getScheduler().scheduleWithFixedDelay(this::calculate, 0, loopTimeMs, TimeUnit.MILLISECONDS);
}
private <T> T requireNonNull(T obj, String message) {
@ -165,24 +170,27 @@ public class PIDControllerTriggerHandler extends BaseTriggerModuleHandler implem
PIDOutputDTO output = controller.calculate(input, setpoint, now - previousTimeMs, loopTimeMs);
previousTimeMs = now;
Map<String, BigDecimal> outputs = new HashMap<>();
updateItem(pInspector, output.getProportionalPart());
updateItem(iInspector, output.getIntegralPart());
updateItem(dInspector, output.getDerivativePart());
updateItem(eInspector, output.getError());
putBigDecimal(outputs, OUTPUT, output.getOutput());
putBigDecimal(outputs, P_INSPECTOR, output.getProportionalPart());
putBigDecimal(outputs, I_INSPECTOR, output.getIntegralPart());
putBigDecimal(outputs, D_INSPECTOR, output.getDerivativePart());
putBigDecimal(outputs, E_INSPECTOR, output.getError());
getCallback().triggered(module, Map.of(COMMAND, new DecimalType(output.getOutput())));
}
ModuleHandlerCallback localCallback = callback;
if (localCallback != null && localCallback instanceof TriggerHandlerCallback) {
((TriggerHandlerCallback) localCallback).triggered(module, outputs);
} else {
logger.warn("No callback set");
private void updateItem(@Nullable String itemName, double value) {
if (itemName != null) {
eventPublisher.post(ItemEventFactory.createCommandEvent(itemName, new DecimalType(value)));
}
}
private void putBigDecimal(Map<String, BigDecimal> map, String key, double value) {
map.put(key, BigDecimal.valueOf(value));
private TriggerHandlerCallback getCallback() {
ModuleHandlerCallback localCallback = callback;
if (localCallback != null && localCallback instanceof TriggerHandlerCallback) {
return (TriggerHandlerCallback) localCallback;
}
throw new IllegalStateException("The module callback is not set");
}
private double getItemValueAsNumber(Item item) throws PIDException {
@ -191,7 +199,7 @@ public class PIDControllerTriggerHandler extends BaseTriggerModuleHandler implem
if (setpointState instanceof Number) {
double doubleValue = ((Number) setpointState).doubleValue();
if (Double.isFinite(doubleValue)) {
if (Double.isFinite(doubleValue) && !Double.isNaN(doubleValue)) {
return doubleValue;
}
} else if (setpointState instanceof StringType) {
@ -237,13 +245,6 @@ public class PIDControllerTriggerHandler extends BaseTriggerModuleHandler implem
public void dispose() {
eventSubscriberRegistration.unregister();
ScheduledFuture<?> localControllerjob = controllerjob;
if (localControllerjob != null) {
localControllerjob.cancel(true);
}
scheduler.shutdown();
super.dispose();
}
}

View File

@ -14,15 +14,11 @@ package org.openhab.automation.pidcontroller.internal.template;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.automation.pidcontroller.internal.PIDControllerConstants;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerActionHandler;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerTriggerHandler;
import org.openhab.automation.pidcontroller.internal.type.PIDControllerActionType;
import org.openhab.core.automation.Action;
import org.openhab.core.automation.Condition;
import org.openhab.core.automation.Trigger;
@ -45,15 +41,8 @@ public class PIDControllerRuleTemplate extends RuleTemplate {
final List<Trigger> triggers = List.of(ModuleBuilder.createTrigger().withId(triggerId)
.withTypeUID(PIDControllerTriggerHandler.MODULE_TYPE_ID).withLabel("PID Controller Trigger").build());
final Map<String, String> actionInputs = Map.of(PIDControllerActionType.INPUT,
triggerId + "." + PIDControllerConstants.OUTPUT);
final List<Action> actions = List.of(ModuleBuilder.createAction().withId(UUID.randomUUID().toString())
.withTypeUID(PIDControllerActionHandler.MODULE_TYPE_ID).withLabel("PID Controller Action")
.withInputs(actionInputs).build());
return new PIDControllerRuleTemplate(Set.of("PID Controller"), triggers, Collections.emptyList(), actions,
Collections.emptyList());
return new PIDControllerRuleTemplate(Set.of("PID Controller"), triggers, Collections.emptyList(),
Collections.emptyList(), Collections.emptyList());
}
public PIDControllerRuleTemplate(Set<String> tags, List<Trigger> triggers, List<Condition> conditions,

View File

@ -1,71 +0,0 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.automation.pidcontroller.internal.type;
import static org.openhab.automation.pidcontroller.internal.PIDControllerConstants.*;
import java.math.BigDecimal;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerActionHandler;
import org.openhab.core.automation.Visibility;
import org.openhab.core.automation.type.ActionType;
import org.openhab.core.automation.type.Input;
import org.openhab.core.config.core.ConfigDescriptionParameter;
import org.openhab.core.config.core.ConfigDescriptionParameter.Type;
import org.openhab.core.config.core.ConfigDescriptionParameterBuilder;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
*/
@NonNullByDefault
public class PIDControllerActionType extends ActionType {
public static final String INPUT = "input";
public static PIDControllerActionType initialize() {
final ConfigDescriptionParameter outputItem = ConfigDescriptionParameterBuilder.create(OUTPUT, Type.TEXT)
.withRequired(true).withMultiple(false).withContext("item").withLabel("Output Item")
.withDescription("Item to send output").build();
final ConfigDescriptionParameter pInspectorItem = ConfigDescriptionParameterBuilder
.create(P_INSPECTOR, Type.TEXT).withRequired(false).withMultiple(false).withContext("item")
.withLabel("P Inspector Item").withDescription("Item for debugging the P part").build();
final ConfigDescriptionParameter iInspectorItem = ConfigDescriptionParameterBuilder
.create(I_INSPECTOR, Type.TEXT).withRequired(false).withMultiple(false).withContext("item")
.withLabel("I Inspector Item").withDescription("Item for debugging the I part").build();
final ConfigDescriptionParameter dInspectorItem = ConfigDescriptionParameterBuilder
.create(D_INSPECTOR, Type.TEXT).withRequired(false).withMultiple(false).withContext("item")
.withLabel("D Inspector Item").withDescription("Item for debugging the D part").build();
final ConfigDescriptionParameter eInspectorItem = ConfigDescriptionParameterBuilder
.create(E_INSPECTOR, Type.TEXT).withRequired(false).withMultiple(false).withContext("item")
.withLabel("Error Inspector Item").withDescription("Item for debugging the error value").build();
List<ConfigDescriptionParameter> config = List.of(outputItem, pInspectorItem, iInspectorItem, dInspectorItem,
eInspectorItem);
List<Input> inputs = List.of(createInput(INPUT), createInput(P_INSPECTOR), createInput(I_INSPECTOR),
createInput(D_INSPECTOR), createInput(E_INSPECTOR));
return new PIDControllerActionType(config, inputs);
}
private static Input createInput(String name) {
return new Input(name, BigDecimal.class.getName());
}
public PIDControllerActionType(List<ConfigDescriptionParameter> configDescriptions, List<Input> inputs) {
super(PIDControllerActionHandler.MODULE_TYPE_ID, configDescriptions, "calculate PID output", null, null,
Visibility.VISIBLE, inputs, null);
}
}

View File

@ -19,7 +19,6 @@ import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerActionHandler;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerTriggerHandler;
import org.openhab.core.automation.type.ModuleType;
import org.openhab.core.automation.type.ModuleTypeProvider;
@ -33,9 +32,8 @@ import org.osgi.service.component.annotations.Component;
@Component
@NonNullByDefault
public class PIDControllerModuleTypeProvider implements ModuleTypeProvider {
private static final Map<String, ModuleType> PROVIDED_MODULE_TYPES = Map.of(
PIDControllerActionHandler.MODULE_TYPE_ID, PIDControllerActionType.initialize(),
PIDControllerTriggerHandler.MODULE_TYPE_ID, PIDControllerTriggerType.initialize());
private static final Map<String, ModuleType> PROVIDED_MODULE_TYPES = Map
.of(PIDControllerTriggerHandler.MODULE_TYPE_ID, PIDControllerTriggerType.initialize());
@SuppressWarnings("unchecked")
@Override

View File

@ -17,6 +17,7 @@ import static org.openhab.automation.pidcontroller.internal.PIDControllerConstan
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerTriggerHandler;
@ -30,24 +31,26 @@ import org.openhab.core.config.core.ConfigDescriptionParameterBuilder;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
* @author Fabian Wolter - Add inspector Items for debugging
*/
@NonNullByDefault
public class PIDControllerTriggerType extends TriggerType {
private static final String DEFAULT_LOOPTIME_MS = "1000";
private static final String ITEM = "item";
public static PIDControllerTriggerType initialize() {
List<ConfigDescriptionParameter> configDescriptions = new ArrayList<>();
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_INPUT_ITEM, Type.TEXT) //
.withRequired(true) //
.withMultiple(false) //
.withContext("item") //
.withContext(ITEM) //
.withLabel("Input Item") //
.withDescription("Item to monitor") //
.build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_SETPOINT_ITEM, Type.TEXT) //
.withRequired(true) //
.withMultiple(false) //
.withContext("item") //
.withContext(ITEM) //
.withLabel("Setpoint") //
.withDescription("Targeted setpoint") //
.build());
@ -83,13 +86,6 @@ public class PIDControllerTriggerType extends TriggerType {
.withDescription("Slows the rate of change of the D part (T1) in seconds.") //
.withUnit("s") //
.build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_COMMAND_ITEM, Type.TEXT) //
.withRequired(false) //
.withMultiple(false) //
.withContext("item") //
.withLabel("Command Item") //
.withDescription("You can send String commands to this Item like \"RESET\".") //
.build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_LOOP_TIME, Type.DECIMAL) //
.withRequired(true) //
.withMultiple(false) //
@ -98,20 +94,37 @@ public class PIDControllerTriggerType extends TriggerType {
.withDescription("The interval the output value is updated in ms") //
.withUnit("ms") //
.build());
Output output = new Output(OUTPUT, BigDecimal.class.getName(), "Output", "Output value of the PID Controller",
null, null, null);
Output pInspector = new Output(P_INSPECTOR, BigDecimal.class.getName(), "P Inspector",
"Current P value of the pid controller", null, null, null);
Output iInspector = new Output(I_INSPECTOR, BigDecimal.class.getName(), "I Inspector",
"Current I value of the pid controller", null, null, null);
Output dInspector = new Output(D_INSPECTOR, BigDecimal.class.getName(), "D Inspector",
"Current D value of the pid controller", null, null, null);
Output eInspector = new Output(E_INSPECTOR, BigDecimal.class.getName(), "Error Value Inspector",
"Current error value of the pid controller", null, null, null);
configDescriptions.add(ConfigDescriptionParameterBuilder.create(P_INSPECTOR, Type.TEXT) //
.withRequired(false) //
.withMultiple(false) //
.withContext(ITEM) //
.withLabel("P Inspector Item") //
.withDescription("Item for debugging the P part") //
.build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(I_INSPECTOR, Type.TEXT) //
.withRequired(false) //
.withMultiple(false) //
.withContext(ITEM) //
.withLabel("I Inspector Item") //
.withDescription("Item for debugging the I part") //
.build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(D_INSPECTOR, Type.TEXT) //
.withRequired(false).withMultiple(false) //
.withContext(ITEM) //
.withLabel("D Inspector Item") //
.withDescription("Item for debugging the D part") //
.build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(E_INSPECTOR, Type.TEXT) //
.withRequired(false).withMultiple(false) //
.withContext(ITEM) //
.withLabel("Error Inspector Item") //
.withDescription("Item for debugging the error value") //
.build());
List<Output> outputs = List.of(output, pInspector, iInspector, dInspector, eInspector);
Output output = new Output(COMMAND, BigDecimal.class.getName(), "Output", "Output value of the PID Controller",
Set.of("command"), null, null);
return new PIDControllerTriggerType(configDescriptions, outputs);
return new PIDControllerTriggerType(configDescriptions, List.of(output));
}
public PIDControllerTriggerType(List<ConfigDescriptionParameter> configDescriptions, List<Output> outputs) {