mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[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:
parent
6141d69da3
commit
cf13bb8275
@ -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:
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user